diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AtlasLoader.js b/src/loaders/AtlasLoader.js deleted file mode 100644 index b46e7f1..0000000 --- a/src/loaders/AtlasLoader.js +++ /dev/null @@ -1,217 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The atlas file loader is used to load in Texture Atlas data and parse it. When loaded this class will dispatch a 'loaded' event. If loading fails this class will dispatch an 'error' event. - * - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format. - * - * It is highly recommended to use texture atlases (also know as 'sprite sheets') as it allowed sprites to be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though Texture.fromFrameId() and Sprite.fromFrameId() - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AtlasLoader(url, crossorigin) -{ - this.url = url; - this.baseUrl = url.replace(/[^\/]*$/, ''); - this.crossorigin = crossorigin; - this.loaded = false; -} - -AtlasLoader.prototype.constructor = AtlasLoader; -module.exports = AtlasLoader; - -core.utils.eventTarget.mixin(AtlasLoader.prototype); - - /** - * Starts loading the JSON file - * - */ -AtlasLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onAtlasLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/json'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the Atlas has fully loaded. Parses the JSON and builds the texture frames. - * - * @private - */ -AtlasLoader.prototype.onAtlasLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.href.indexOf('http') === -1) - { - this.atlas = { - meta : { - image : [] - }, - frames : [] - }; - var result = this.ajaxRequest.responseText.split(/\r?\n/); - var lineCount = -3; - - var currentImageId = 0; - var currentFrame = null; - var nameInNextLine = false; - - var i = 0, - j = 0, - selfOnLoaded = this.onLoaded.bind(this); - - // parser without rotation support yet! - for (i = 0; i < result.length; i++) - { - result[i] = result[i].replace(/^\s+|\s+$/g, ''); - - if (result[i] === '') - { - nameInNextLine = i+1; - } - - if (result[i].length > 0) - { - if (nameInNextLine === i) - { - this.atlas.meta.image.push(result[i]); - currentImageId = this.atlas.meta.image.length - 1; - this.atlas.frames.push({}); - lineCount = -3; - } else if (lineCount > 0) - { - if (lineCount % 7 === 1) - { // frame name - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - currentFrame = { name: result[i], frame : {} }; - } else { - var text = result[i].split(' '); - if (lineCount % 7 === 3) - { // position - currentFrame.frame.x = Number(text[1].replace(',', '')); - currentFrame.frame.y = Number(text[2]); - } else if (lineCount % 7 === 4) - { // size - currentFrame.frame.w = Number(text[1].replace(',', '')); - currentFrame.frame.h = Number(text[2]); - } else if (lineCount % 7 === 5) - { // real size - var realSize = { - x : 0, - y : 0, - w : Number(text[1].replace(',', '')), - h : Number(text[2]) - }; - - if (realSize.w > currentFrame.frame.w || realSize.h > currentFrame.frame.h) - { - currentFrame.trimmed = true; - currentFrame.realSize = realSize; - } else { - currentFrame.trimmed = false; - } - } - } - } - lineCount++; - } - } - - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - - if (this.atlas.meta.image.length > 0) - { - this.images = []; - for (j = 0; j < this.atlas.meta.image.length; j++) - { - // sprite sheet - var textureUrl = this.baseUrl + this.atlas.meta.image[j]; - var frameData = this.atlas.frames[j]; - this.images.push(new ImageLoader(textureUrl, this.crossorigin)); - - for (i in frameData) - { - var rect = frameData[i].frame; - if (rect) - { - core.utils.TextureCache[i] = new core.Texture(this.images[j].texture.baseTexture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) - { - core.utils.TextureCache[i].realSize = frameData[i].realSize; - // trim in pixi not supported yet, todo update trim properties if it is done ... - core.utils.TextureCache[i].trim.x = 0; - core.utils.TextureCache[i].trim.y = 0; - } - } - } - } - - this.currentImageId = 0; - for (j = 0; j < this.images.length; j++) - { - this.images[j].on('loaded', selfOnLoaded); - } - this.images[this.currentImageId].load(); - - } else { - this.onLoaded(); - } - - } else { - this.onError(); - } - } -}; - -/** - * Invoked when json file has loaded. - * - * @private - */ -AtlasLoader.prototype.onLoaded = function () -{ - if (this.images.length - 1 > this.currentImageId) - { - this.currentImageId++; - this.images[this.currentImageId].load(); - } else { - this.loaded = true; - this.emit('loaded', { content: this }); - } -}; - -/** - * Invoked when an error occurs. - * - * @private - */ -AtlasLoader.prototype.onError = function () -{ - this.emit('error', { content: this }); -}; diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AtlasLoader.js b/src/loaders/AtlasLoader.js deleted file mode 100644 index b46e7f1..0000000 --- a/src/loaders/AtlasLoader.js +++ /dev/null @@ -1,217 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The atlas file loader is used to load in Texture Atlas data and parse it. When loaded this class will dispatch a 'loaded' event. If loading fails this class will dispatch an 'error' event. - * - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format. - * - * It is highly recommended to use texture atlases (also know as 'sprite sheets') as it allowed sprites to be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though Texture.fromFrameId() and Sprite.fromFrameId() - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AtlasLoader(url, crossorigin) -{ - this.url = url; - this.baseUrl = url.replace(/[^\/]*$/, ''); - this.crossorigin = crossorigin; - this.loaded = false; -} - -AtlasLoader.prototype.constructor = AtlasLoader; -module.exports = AtlasLoader; - -core.utils.eventTarget.mixin(AtlasLoader.prototype); - - /** - * Starts loading the JSON file - * - */ -AtlasLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onAtlasLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/json'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the Atlas has fully loaded. Parses the JSON and builds the texture frames. - * - * @private - */ -AtlasLoader.prototype.onAtlasLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.href.indexOf('http') === -1) - { - this.atlas = { - meta : { - image : [] - }, - frames : [] - }; - var result = this.ajaxRequest.responseText.split(/\r?\n/); - var lineCount = -3; - - var currentImageId = 0; - var currentFrame = null; - var nameInNextLine = false; - - var i = 0, - j = 0, - selfOnLoaded = this.onLoaded.bind(this); - - // parser without rotation support yet! - for (i = 0; i < result.length; i++) - { - result[i] = result[i].replace(/^\s+|\s+$/g, ''); - - if (result[i] === '') - { - nameInNextLine = i+1; - } - - if (result[i].length > 0) - { - if (nameInNextLine === i) - { - this.atlas.meta.image.push(result[i]); - currentImageId = this.atlas.meta.image.length - 1; - this.atlas.frames.push({}); - lineCount = -3; - } else if (lineCount > 0) - { - if (lineCount % 7 === 1) - { // frame name - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - currentFrame = { name: result[i], frame : {} }; - } else { - var text = result[i].split(' '); - if (lineCount % 7 === 3) - { // position - currentFrame.frame.x = Number(text[1].replace(',', '')); - currentFrame.frame.y = Number(text[2]); - } else if (lineCount % 7 === 4) - { // size - currentFrame.frame.w = Number(text[1].replace(',', '')); - currentFrame.frame.h = Number(text[2]); - } else if (lineCount % 7 === 5) - { // real size - var realSize = { - x : 0, - y : 0, - w : Number(text[1].replace(',', '')), - h : Number(text[2]) - }; - - if (realSize.w > currentFrame.frame.w || realSize.h > currentFrame.frame.h) - { - currentFrame.trimmed = true; - currentFrame.realSize = realSize; - } else { - currentFrame.trimmed = false; - } - } - } - } - lineCount++; - } - } - - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - - if (this.atlas.meta.image.length > 0) - { - this.images = []; - for (j = 0; j < this.atlas.meta.image.length; j++) - { - // sprite sheet - var textureUrl = this.baseUrl + this.atlas.meta.image[j]; - var frameData = this.atlas.frames[j]; - this.images.push(new ImageLoader(textureUrl, this.crossorigin)); - - for (i in frameData) - { - var rect = frameData[i].frame; - if (rect) - { - core.utils.TextureCache[i] = new core.Texture(this.images[j].texture.baseTexture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) - { - core.utils.TextureCache[i].realSize = frameData[i].realSize; - // trim in pixi not supported yet, todo update trim properties if it is done ... - core.utils.TextureCache[i].trim.x = 0; - core.utils.TextureCache[i].trim.y = 0; - } - } - } - } - - this.currentImageId = 0; - for (j = 0; j < this.images.length; j++) - { - this.images[j].on('loaded', selfOnLoaded); - } - this.images[this.currentImageId].load(); - - } else { - this.onLoaded(); - } - - } else { - this.onError(); - } - } -}; - -/** - * Invoked when json file has loaded. - * - * @private - */ -AtlasLoader.prototype.onLoaded = function () -{ - if (this.images.length - 1 > this.currentImageId) - { - this.currentImageId++; - this.images[this.currentImageId].load(); - } else { - this.loaded = true; - this.emit('loaded', { content: this }); - } -}; - -/** - * Invoked when an error occurs. - * - * @private - */ -AtlasLoader.prototype.onError = function () -{ - this.emit('error', { content: this }); -}; diff --git a/src/loaders/BitmapFontLoader.js b/src/loaders/BitmapFontLoader.js deleted file mode 100644 index 13e5c1b..0000000 --- a/src/loaders/BitmapFontLoader.js +++ /dev/null @@ -1,162 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The xml loader is used to load in XML bitmap font data ('xml' or 'fnt') - * To generate the data you can use http://www.angelcode.com/products/bmfont/ - * This loader will also load the image file as the data. - * When loaded this class will dispatch a 'loaded' event - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function BitmapFontLoader(url, crossorigin) -{ - /** - * The url of the bitmap font data - * - * @member {String} - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * The base url of the bitmap font data - * - * @member {String} - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ''); - - /** - * The texture of the bitmap font - * - * @member {Texture} - */ - this.texture = null; -} - -// constructor -BitmapFontLoader.prototype.constructor = BitmapFontLoader; -module.exports = BitmapFontLoader; - -core.utils.eventTarget.mixin(BitmapFontLoader.prototype); - -/** - * Loads the XML font data - * - */ -BitmapFontLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onXMLLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/xml'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the XML file is loaded, parses the data. - * - * @private - */ -BitmapFontLoader.prototype.onXMLLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.protocol.indexOf('http') === -1) - { - var responseXML = this.ajaxRequest.responseXML; - if (!responseXML || /MSIE 9/i.test(navigator.userAgent) || navigator.isCocoonJS) - { - if (typeof(window.DOMParser) === 'function') - { - var domparser = new DOMParser(); - responseXML = domparser.parseFromString(this.ajaxRequest.responseText, 'text/xml'); - } else { - var div = document.createElement('div'); - div.innerHTML = this.ajaxRequest.responseText; - responseXML = div; - } - } - - var textureUrl = this.baseUrl + responseXML.getElementsByTagName('page')[0].getAttribute('file'); - var image = new ImageLoader(textureUrl, this.crossorigin); - this.texture = image.texture.baseTexture; - - var data = {}; - var info = responseXML.getElementsByTagName('info')[0]; - var common = responseXML.getElementsByTagName('common')[0]; - data.font = info.getAttribute('face'); - data.size = parseInt(info.getAttribute('size'), 10); - data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); - data.chars = {}; - - //parse letters - var letters = responseXML.getElementsByTagName('char'); - - for (var i = 0; i < letters.length; i++) - { - var charCode = parseInt(letters[i].getAttribute('id'), 10); - - var textureRect = new core.math.Rectangle( - parseInt(letters[i].getAttribute('x'), 10), - parseInt(letters[i].getAttribute('y'), 10), - parseInt(letters[i].getAttribute('width'), 10), - parseInt(letters[i].getAttribute('height'), 10) - ); - - data.chars[charCode] = { - xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), - yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), - xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), - kerning: {}, - texture: core.utils.TextureCache[charCode] = new core.Texture(this.texture, textureRect) - - }; - } - - //parse kernings - var kernings = responseXML.getElementsByTagName('kerning'); - for (i = 0; i < kernings.length; i++) - { - var first = parseInt(kernings[i].getAttribute('first'), 10); - var second = parseInt(kernings[i].getAttribute('second'), 10); - var amount = parseInt(kernings[i].getAttribute('amount'), 10); - - data.chars[second].kerning[first] = amount; - - } - - core.BitmapText.fonts[data.font] = data; - - image.addEventListener('loaded', this.onLoaded.bind(this)); - image.load(); - } - } -}; - -/** - * Invoked when all files are loaded (xml/fnt and texture) - * - * @private - */ -BitmapFontLoader.prototype.onLoaded = function () -{ - this.emit('loaded', { content: this }); -}; diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AtlasLoader.js b/src/loaders/AtlasLoader.js deleted file mode 100644 index b46e7f1..0000000 --- a/src/loaders/AtlasLoader.js +++ /dev/null @@ -1,217 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The atlas file loader is used to load in Texture Atlas data and parse it. When loaded this class will dispatch a 'loaded' event. If loading fails this class will dispatch an 'error' event. - * - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format. - * - * It is highly recommended to use texture atlases (also know as 'sprite sheets') as it allowed sprites to be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though Texture.fromFrameId() and Sprite.fromFrameId() - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AtlasLoader(url, crossorigin) -{ - this.url = url; - this.baseUrl = url.replace(/[^\/]*$/, ''); - this.crossorigin = crossorigin; - this.loaded = false; -} - -AtlasLoader.prototype.constructor = AtlasLoader; -module.exports = AtlasLoader; - -core.utils.eventTarget.mixin(AtlasLoader.prototype); - - /** - * Starts loading the JSON file - * - */ -AtlasLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onAtlasLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/json'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the Atlas has fully loaded. Parses the JSON and builds the texture frames. - * - * @private - */ -AtlasLoader.prototype.onAtlasLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.href.indexOf('http') === -1) - { - this.atlas = { - meta : { - image : [] - }, - frames : [] - }; - var result = this.ajaxRequest.responseText.split(/\r?\n/); - var lineCount = -3; - - var currentImageId = 0; - var currentFrame = null; - var nameInNextLine = false; - - var i = 0, - j = 0, - selfOnLoaded = this.onLoaded.bind(this); - - // parser without rotation support yet! - for (i = 0; i < result.length; i++) - { - result[i] = result[i].replace(/^\s+|\s+$/g, ''); - - if (result[i] === '') - { - nameInNextLine = i+1; - } - - if (result[i].length > 0) - { - if (nameInNextLine === i) - { - this.atlas.meta.image.push(result[i]); - currentImageId = this.atlas.meta.image.length - 1; - this.atlas.frames.push({}); - lineCount = -3; - } else if (lineCount > 0) - { - if (lineCount % 7 === 1) - { // frame name - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - currentFrame = { name: result[i], frame : {} }; - } else { - var text = result[i].split(' '); - if (lineCount % 7 === 3) - { // position - currentFrame.frame.x = Number(text[1].replace(',', '')); - currentFrame.frame.y = Number(text[2]); - } else if (lineCount % 7 === 4) - { // size - currentFrame.frame.w = Number(text[1].replace(',', '')); - currentFrame.frame.h = Number(text[2]); - } else if (lineCount % 7 === 5) - { // real size - var realSize = { - x : 0, - y : 0, - w : Number(text[1].replace(',', '')), - h : Number(text[2]) - }; - - if (realSize.w > currentFrame.frame.w || realSize.h > currentFrame.frame.h) - { - currentFrame.trimmed = true; - currentFrame.realSize = realSize; - } else { - currentFrame.trimmed = false; - } - } - } - } - lineCount++; - } - } - - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - - if (this.atlas.meta.image.length > 0) - { - this.images = []; - for (j = 0; j < this.atlas.meta.image.length; j++) - { - // sprite sheet - var textureUrl = this.baseUrl + this.atlas.meta.image[j]; - var frameData = this.atlas.frames[j]; - this.images.push(new ImageLoader(textureUrl, this.crossorigin)); - - for (i in frameData) - { - var rect = frameData[i].frame; - if (rect) - { - core.utils.TextureCache[i] = new core.Texture(this.images[j].texture.baseTexture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) - { - core.utils.TextureCache[i].realSize = frameData[i].realSize; - // trim in pixi not supported yet, todo update trim properties if it is done ... - core.utils.TextureCache[i].trim.x = 0; - core.utils.TextureCache[i].trim.y = 0; - } - } - } - } - - this.currentImageId = 0; - for (j = 0; j < this.images.length; j++) - { - this.images[j].on('loaded', selfOnLoaded); - } - this.images[this.currentImageId].load(); - - } else { - this.onLoaded(); - } - - } else { - this.onError(); - } - } -}; - -/** - * Invoked when json file has loaded. - * - * @private - */ -AtlasLoader.prototype.onLoaded = function () -{ - if (this.images.length - 1 > this.currentImageId) - { - this.currentImageId++; - this.images[this.currentImageId].load(); - } else { - this.loaded = true; - this.emit('loaded', { content: this }); - } -}; - -/** - * Invoked when an error occurs. - * - * @private - */ -AtlasLoader.prototype.onError = function () -{ - this.emit('error', { content: this }); -}; diff --git a/src/loaders/BitmapFontLoader.js b/src/loaders/BitmapFontLoader.js deleted file mode 100644 index 13e5c1b..0000000 --- a/src/loaders/BitmapFontLoader.js +++ /dev/null @@ -1,162 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The xml loader is used to load in XML bitmap font data ('xml' or 'fnt') - * To generate the data you can use http://www.angelcode.com/products/bmfont/ - * This loader will also load the image file as the data. - * When loaded this class will dispatch a 'loaded' event - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function BitmapFontLoader(url, crossorigin) -{ - /** - * The url of the bitmap font data - * - * @member {String} - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * The base url of the bitmap font data - * - * @member {String} - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ''); - - /** - * The texture of the bitmap font - * - * @member {Texture} - */ - this.texture = null; -} - -// constructor -BitmapFontLoader.prototype.constructor = BitmapFontLoader; -module.exports = BitmapFontLoader; - -core.utils.eventTarget.mixin(BitmapFontLoader.prototype); - -/** - * Loads the XML font data - * - */ -BitmapFontLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onXMLLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/xml'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the XML file is loaded, parses the data. - * - * @private - */ -BitmapFontLoader.prototype.onXMLLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.protocol.indexOf('http') === -1) - { - var responseXML = this.ajaxRequest.responseXML; - if (!responseXML || /MSIE 9/i.test(navigator.userAgent) || navigator.isCocoonJS) - { - if (typeof(window.DOMParser) === 'function') - { - var domparser = new DOMParser(); - responseXML = domparser.parseFromString(this.ajaxRequest.responseText, 'text/xml'); - } else { - var div = document.createElement('div'); - div.innerHTML = this.ajaxRequest.responseText; - responseXML = div; - } - } - - var textureUrl = this.baseUrl + responseXML.getElementsByTagName('page')[0].getAttribute('file'); - var image = new ImageLoader(textureUrl, this.crossorigin); - this.texture = image.texture.baseTexture; - - var data = {}; - var info = responseXML.getElementsByTagName('info')[0]; - var common = responseXML.getElementsByTagName('common')[0]; - data.font = info.getAttribute('face'); - data.size = parseInt(info.getAttribute('size'), 10); - data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); - data.chars = {}; - - //parse letters - var letters = responseXML.getElementsByTagName('char'); - - for (var i = 0; i < letters.length; i++) - { - var charCode = parseInt(letters[i].getAttribute('id'), 10); - - var textureRect = new core.math.Rectangle( - parseInt(letters[i].getAttribute('x'), 10), - parseInt(letters[i].getAttribute('y'), 10), - parseInt(letters[i].getAttribute('width'), 10), - parseInt(letters[i].getAttribute('height'), 10) - ); - - data.chars[charCode] = { - xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), - yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), - xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), - kerning: {}, - texture: core.utils.TextureCache[charCode] = new core.Texture(this.texture, textureRect) - - }; - } - - //parse kernings - var kernings = responseXML.getElementsByTagName('kerning'); - for (i = 0; i < kernings.length; i++) - { - var first = parseInt(kernings[i].getAttribute('first'), 10); - var second = parseInt(kernings[i].getAttribute('second'), 10); - var amount = parseInt(kernings[i].getAttribute('amount'), 10); - - data.chars[second].kerning[first] = amount; - - } - - core.BitmapText.fonts[data.font] = data; - - image.addEventListener('loaded', this.onLoaded.bind(this)); - image.load(); - } - } -}; - -/** - * Invoked when all files are loaded (xml/fnt and texture) - * - * @private - */ -BitmapFontLoader.prototype.onLoaded = function () -{ - this.emit('loaded', { content: this }); -}; diff --git a/src/loaders/SpineTextureLoader.js b/src/loaders/SpineTextureLoader.js deleted file mode 100644 index c09a548..0000000 --- a/src/loaders/SpineTextureLoader.js +++ /dev/null @@ -1,56 +0,0 @@ -var core = require('../core'); - -/** - * Supporting class to load images from spine atlases as per spine spec. - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @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 - */ -function SpineTextureLoader(basePath, crossorigin) -{ - this.basePath = basePath; - this.crossorigin = crossorigin; - this.loadingCount = 0; -} - -SpineTextureLoader.prototype.constructor = SpineTextureLoader; -module.exports = SpineTextureLoader; - -core.utils.eventTarget.mixin(SpineTextureLoader.prototype); - -/** - * Starts loading a base texture as per spine specification - * - * @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 - */ -SpineTextureLoader.prototype.load = function (page, file) -{ - page.rendererObject = core.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 - * - * @param texture {BaseTexture} Texture object to destroy - */ -SpineTextureLoader.prototype.unload = function (texture) -{ - texture.destroy(true); -}; diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AtlasLoader.js b/src/loaders/AtlasLoader.js deleted file mode 100644 index b46e7f1..0000000 --- a/src/loaders/AtlasLoader.js +++ /dev/null @@ -1,217 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The atlas file loader is used to load in Texture Atlas data and parse it. When loaded this class will dispatch a 'loaded' event. If loading fails this class will dispatch an 'error' event. - * - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format. - * - * It is highly recommended to use texture atlases (also know as 'sprite sheets') as it allowed sprites to be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though Texture.fromFrameId() and Sprite.fromFrameId() - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AtlasLoader(url, crossorigin) -{ - this.url = url; - this.baseUrl = url.replace(/[^\/]*$/, ''); - this.crossorigin = crossorigin; - this.loaded = false; -} - -AtlasLoader.prototype.constructor = AtlasLoader; -module.exports = AtlasLoader; - -core.utils.eventTarget.mixin(AtlasLoader.prototype); - - /** - * Starts loading the JSON file - * - */ -AtlasLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onAtlasLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/json'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the Atlas has fully loaded. Parses the JSON and builds the texture frames. - * - * @private - */ -AtlasLoader.prototype.onAtlasLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.href.indexOf('http') === -1) - { - this.atlas = { - meta : { - image : [] - }, - frames : [] - }; - var result = this.ajaxRequest.responseText.split(/\r?\n/); - var lineCount = -3; - - var currentImageId = 0; - var currentFrame = null; - var nameInNextLine = false; - - var i = 0, - j = 0, - selfOnLoaded = this.onLoaded.bind(this); - - // parser without rotation support yet! - for (i = 0; i < result.length; i++) - { - result[i] = result[i].replace(/^\s+|\s+$/g, ''); - - if (result[i] === '') - { - nameInNextLine = i+1; - } - - if (result[i].length > 0) - { - if (nameInNextLine === i) - { - this.atlas.meta.image.push(result[i]); - currentImageId = this.atlas.meta.image.length - 1; - this.atlas.frames.push({}); - lineCount = -3; - } else if (lineCount > 0) - { - if (lineCount % 7 === 1) - { // frame name - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - currentFrame = { name: result[i], frame : {} }; - } else { - var text = result[i].split(' '); - if (lineCount % 7 === 3) - { // position - currentFrame.frame.x = Number(text[1].replace(',', '')); - currentFrame.frame.y = Number(text[2]); - } else if (lineCount % 7 === 4) - { // size - currentFrame.frame.w = Number(text[1].replace(',', '')); - currentFrame.frame.h = Number(text[2]); - } else if (lineCount % 7 === 5) - { // real size - var realSize = { - x : 0, - y : 0, - w : Number(text[1].replace(',', '')), - h : Number(text[2]) - }; - - if (realSize.w > currentFrame.frame.w || realSize.h > currentFrame.frame.h) - { - currentFrame.trimmed = true; - currentFrame.realSize = realSize; - } else { - currentFrame.trimmed = false; - } - } - } - } - lineCount++; - } - } - - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - - if (this.atlas.meta.image.length > 0) - { - this.images = []; - for (j = 0; j < this.atlas.meta.image.length; j++) - { - // sprite sheet - var textureUrl = this.baseUrl + this.atlas.meta.image[j]; - var frameData = this.atlas.frames[j]; - this.images.push(new ImageLoader(textureUrl, this.crossorigin)); - - for (i in frameData) - { - var rect = frameData[i].frame; - if (rect) - { - core.utils.TextureCache[i] = new core.Texture(this.images[j].texture.baseTexture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) - { - core.utils.TextureCache[i].realSize = frameData[i].realSize; - // trim in pixi not supported yet, todo update trim properties if it is done ... - core.utils.TextureCache[i].trim.x = 0; - core.utils.TextureCache[i].trim.y = 0; - } - } - } - } - - this.currentImageId = 0; - for (j = 0; j < this.images.length; j++) - { - this.images[j].on('loaded', selfOnLoaded); - } - this.images[this.currentImageId].load(); - - } else { - this.onLoaded(); - } - - } else { - this.onError(); - } - } -}; - -/** - * Invoked when json file has loaded. - * - * @private - */ -AtlasLoader.prototype.onLoaded = function () -{ - if (this.images.length - 1 > this.currentImageId) - { - this.currentImageId++; - this.images[this.currentImageId].load(); - } else { - this.loaded = true; - this.emit('loaded', { content: this }); - } -}; - -/** - * Invoked when an error occurs. - * - * @private - */ -AtlasLoader.prototype.onError = function () -{ - this.emit('error', { content: this }); -}; diff --git a/src/loaders/BitmapFontLoader.js b/src/loaders/BitmapFontLoader.js deleted file mode 100644 index 13e5c1b..0000000 --- a/src/loaders/BitmapFontLoader.js +++ /dev/null @@ -1,162 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The xml loader is used to load in XML bitmap font data ('xml' or 'fnt') - * To generate the data you can use http://www.angelcode.com/products/bmfont/ - * This loader will also load the image file as the data. - * When loaded this class will dispatch a 'loaded' event - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function BitmapFontLoader(url, crossorigin) -{ - /** - * The url of the bitmap font data - * - * @member {String} - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * The base url of the bitmap font data - * - * @member {String} - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ''); - - /** - * The texture of the bitmap font - * - * @member {Texture} - */ - this.texture = null; -} - -// constructor -BitmapFontLoader.prototype.constructor = BitmapFontLoader; -module.exports = BitmapFontLoader; - -core.utils.eventTarget.mixin(BitmapFontLoader.prototype); - -/** - * Loads the XML font data - * - */ -BitmapFontLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onXMLLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/xml'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the XML file is loaded, parses the data. - * - * @private - */ -BitmapFontLoader.prototype.onXMLLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.protocol.indexOf('http') === -1) - { - var responseXML = this.ajaxRequest.responseXML; - if (!responseXML || /MSIE 9/i.test(navigator.userAgent) || navigator.isCocoonJS) - { - if (typeof(window.DOMParser) === 'function') - { - var domparser = new DOMParser(); - responseXML = domparser.parseFromString(this.ajaxRequest.responseText, 'text/xml'); - } else { - var div = document.createElement('div'); - div.innerHTML = this.ajaxRequest.responseText; - responseXML = div; - } - } - - var textureUrl = this.baseUrl + responseXML.getElementsByTagName('page')[0].getAttribute('file'); - var image = new ImageLoader(textureUrl, this.crossorigin); - this.texture = image.texture.baseTexture; - - var data = {}; - var info = responseXML.getElementsByTagName('info')[0]; - var common = responseXML.getElementsByTagName('common')[0]; - data.font = info.getAttribute('face'); - data.size = parseInt(info.getAttribute('size'), 10); - data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); - data.chars = {}; - - //parse letters - var letters = responseXML.getElementsByTagName('char'); - - for (var i = 0; i < letters.length; i++) - { - var charCode = parseInt(letters[i].getAttribute('id'), 10); - - var textureRect = new core.math.Rectangle( - parseInt(letters[i].getAttribute('x'), 10), - parseInt(letters[i].getAttribute('y'), 10), - parseInt(letters[i].getAttribute('width'), 10), - parseInt(letters[i].getAttribute('height'), 10) - ); - - data.chars[charCode] = { - xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), - yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), - xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), - kerning: {}, - texture: core.utils.TextureCache[charCode] = new core.Texture(this.texture, textureRect) - - }; - } - - //parse kernings - var kernings = responseXML.getElementsByTagName('kerning'); - for (i = 0; i < kernings.length; i++) - { - var first = parseInt(kernings[i].getAttribute('first'), 10); - var second = parseInt(kernings[i].getAttribute('second'), 10); - var amount = parseInt(kernings[i].getAttribute('amount'), 10); - - data.chars[second].kerning[first] = amount; - - } - - core.BitmapText.fonts[data.font] = data; - - image.addEventListener('loaded', this.onLoaded.bind(this)); - image.load(); - } - } -}; - -/** - * Invoked when all files are loaded (xml/fnt and texture) - * - * @private - */ -BitmapFontLoader.prototype.onLoaded = function () -{ - this.emit('loaded', { content: this }); -}; diff --git a/src/loaders/SpineTextureLoader.js b/src/loaders/SpineTextureLoader.js deleted file mode 100644 index c09a548..0000000 --- a/src/loaders/SpineTextureLoader.js +++ /dev/null @@ -1,56 +0,0 @@ -var core = require('../core'); - -/** - * Supporting class to load images from spine atlases as per spine spec. - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @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 - */ -function SpineTextureLoader(basePath, crossorigin) -{ - this.basePath = basePath; - this.crossorigin = crossorigin; - this.loadingCount = 0; -} - -SpineTextureLoader.prototype.constructor = SpineTextureLoader; -module.exports = SpineTextureLoader; - -core.utils.eventTarget.mixin(SpineTextureLoader.prototype); - -/** - * Starts loading a base texture as per spine specification - * - * @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 - */ -SpineTextureLoader.prototype.load = function (page, file) -{ - page.rendererObject = core.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 - * - * @param texture {BaseTexture} Texture object to destroy - */ -SpineTextureLoader.prototype.unload = function (texture) -{ - texture.destroy(true); -}; diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js new file mode 100644 index 0000000..6320ae4 --- /dev/null +++ b/src/loaders/bitmapFontParser.js @@ -0,0 +1,88 @@ +var Resource = require('asset-loader').Resource, + core = require('../core'); + +module.exports = function () +{ + return function (resource, next) + { + if (!resource.data || navigator.isCocoonJS) + { + if (window.DOMParser) + { + var domparser = new DOMParser(); + resource.data = domparser.parseFromString(this.xhr.responseText, 'text/xml'); + } + else + { + var div = document.createElement('div'); + div.innerHTML = this.xhr.responseText; + resource.data = div; + } + } + + // skip if no data + if (!resource.data) + { + return next(); + } + + var textureUrl = this.baseUrl + resource.data.getElementsByTagName('page')[0].getAttribute('file'); + var loadOptions = { + crossOrigin: resource.crossOrigin, + loadType: Resource.LOAD_TYPE.IMAGE + }; + + // load the texture for the font + this.loadResource(new Resource(textureUrl, loadOptions), function (res) + { + var data = {}; + var info = resource.data.getElementsByTagName('info')[0]; + var common = resource.data.getElementsByTagName('common')[0]; + + data.font = info.getAttribute('face'); + data.size = parseInt(info.getAttribute('size'), 10); + data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); + data.chars = {}; + + //parse letters + var letters = resource.data.getElementsByTagName('char'); + + for (var i = 0; i < letters.length; i++) + { + var charCode = parseInt(letters[i].getAttribute('id'), 10); + + var textureRect = new core.math.Rectangle( + parseInt(letters[i].getAttribute('x'), 10), + parseInt(letters[i].getAttribute('y'), 10), + parseInt(letters[i].getAttribute('width'), 10), + parseInt(letters[i].getAttribute('height'), 10) + ); + + data.chars[charCode] = { + xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), + yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), + xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), + kerning: {}, + texture: core.utils.TextureCache[charCode] = new core.Texture(res.texture.baseTexture, textureRect) + + }; + } + + //parse kernings + var kernings = resource.data.getElementsByTagName('kerning'); + for (i = 0; i < kernings.length; i++) + { + var first = parseInt(kernings[i].getAttribute('first'), 10); + var second = parseInt(kernings[i].getAttribute('second'), 10); + var amount = parseInt(kernings[i].getAttribute('amount'), 10); + + data.chars[second].kerning[first] = amount; + + } + + resource.bitmapFont = data; + + next(); + }); + }; +}; diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AtlasLoader.js b/src/loaders/AtlasLoader.js deleted file mode 100644 index b46e7f1..0000000 --- a/src/loaders/AtlasLoader.js +++ /dev/null @@ -1,217 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The atlas file loader is used to load in Texture Atlas data and parse it. When loaded this class will dispatch a 'loaded' event. If loading fails this class will dispatch an 'error' event. - * - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format. - * - * It is highly recommended to use texture atlases (also know as 'sprite sheets') as it allowed sprites to be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though Texture.fromFrameId() and Sprite.fromFrameId() - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AtlasLoader(url, crossorigin) -{ - this.url = url; - this.baseUrl = url.replace(/[^\/]*$/, ''); - this.crossorigin = crossorigin; - this.loaded = false; -} - -AtlasLoader.prototype.constructor = AtlasLoader; -module.exports = AtlasLoader; - -core.utils.eventTarget.mixin(AtlasLoader.prototype); - - /** - * Starts loading the JSON file - * - */ -AtlasLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onAtlasLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/json'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the Atlas has fully loaded. Parses the JSON and builds the texture frames. - * - * @private - */ -AtlasLoader.prototype.onAtlasLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.href.indexOf('http') === -1) - { - this.atlas = { - meta : { - image : [] - }, - frames : [] - }; - var result = this.ajaxRequest.responseText.split(/\r?\n/); - var lineCount = -3; - - var currentImageId = 0; - var currentFrame = null; - var nameInNextLine = false; - - var i = 0, - j = 0, - selfOnLoaded = this.onLoaded.bind(this); - - // parser without rotation support yet! - for (i = 0; i < result.length; i++) - { - result[i] = result[i].replace(/^\s+|\s+$/g, ''); - - if (result[i] === '') - { - nameInNextLine = i+1; - } - - if (result[i].length > 0) - { - if (nameInNextLine === i) - { - this.atlas.meta.image.push(result[i]); - currentImageId = this.atlas.meta.image.length - 1; - this.atlas.frames.push({}); - lineCount = -3; - } else if (lineCount > 0) - { - if (lineCount % 7 === 1) - { // frame name - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - currentFrame = { name: result[i], frame : {} }; - } else { - var text = result[i].split(' '); - if (lineCount % 7 === 3) - { // position - currentFrame.frame.x = Number(text[1].replace(',', '')); - currentFrame.frame.y = Number(text[2]); - } else if (lineCount % 7 === 4) - { // size - currentFrame.frame.w = Number(text[1].replace(',', '')); - currentFrame.frame.h = Number(text[2]); - } else if (lineCount % 7 === 5) - { // real size - var realSize = { - x : 0, - y : 0, - w : Number(text[1].replace(',', '')), - h : Number(text[2]) - }; - - if (realSize.w > currentFrame.frame.w || realSize.h > currentFrame.frame.h) - { - currentFrame.trimmed = true; - currentFrame.realSize = realSize; - } else { - currentFrame.trimmed = false; - } - } - } - } - lineCount++; - } - } - - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - - if (this.atlas.meta.image.length > 0) - { - this.images = []; - for (j = 0; j < this.atlas.meta.image.length; j++) - { - // sprite sheet - var textureUrl = this.baseUrl + this.atlas.meta.image[j]; - var frameData = this.atlas.frames[j]; - this.images.push(new ImageLoader(textureUrl, this.crossorigin)); - - for (i in frameData) - { - var rect = frameData[i].frame; - if (rect) - { - core.utils.TextureCache[i] = new core.Texture(this.images[j].texture.baseTexture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) - { - core.utils.TextureCache[i].realSize = frameData[i].realSize; - // trim in pixi not supported yet, todo update trim properties if it is done ... - core.utils.TextureCache[i].trim.x = 0; - core.utils.TextureCache[i].trim.y = 0; - } - } - } - } - - this.currentImageId = 0; - for (j = 0; j < this.images.length; j++) - { - this.images[j].on('loaded', selfOnLoaded); - } - this.images[this.currentImageId].load(); - - } else { - this.onLoaded(); - } - - } else { - this.onError(); - } - } -}; - -/** - * Invoked when json file has loaded. - * - * @private - */ -AtlasLoader.prototype.onLoaded = function () -{ - if (this.images.length - 1 > this.currentImageId) - { - this.currentImageId++; - this.images[this.currentImageId].load(); - } else { - this.loaded = true; - this.emit('loaded', { content: this }); - } -}; - -/** - * Invoked when an error occurs. - * - * @private - */ -AtlasLoader.prototype.onError = function () -{ - this.emit('error', { content: this }); -}; diff --git a/src/loaders/BitmapFontLoader.js b/src/loaders/BitmapFontLoader.js deleted file mode 100644 index 13e5c1b..0000000 --- a/src/loaders/BitmapFontLoader.js +++ /dev/null @@ -1,162 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The xml loader is used to load in XML bitmap font data ('xml' or 'fnt') - * To generate the data you can use http://www.angelcode.com/products/bmfont/ - * This loader will also load the image file as the data. - * When loaded this class will dispatch a 'loaded' event - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function BitmapFontLoader(url, crossorigin) -{ - /** - * The url of the bitmap font data - * - * @member {String} - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * The base url of the bitmap font data - * - * @member {String} - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ''); - - /** - * The texture of the bitmap font - * - * @member {Texture} - */ - this.texture = null; -} - -// constructor -BitmapFontLoader.prototype.constructor = BitmapFontLoader; -module.exports = BitmapFontLoader; - -core.utils.eventTarget.mixin(BitmapFontLoader.prototype); - -/** - * Loads the XML font data - * - */ -BitmapFontLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onXMLLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/xml'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the XML file is loaded, parses the data. - * - * @private - */ -BitmapFontLoader.prototype.onXMLLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.protocol.indexOf('http') === -1) - { - var responseXML = this.ajaxRequest.responseXML; - if (!responseXML || /MSIE 9/i.test(navigator.userAgent) || navigator.isCocoonJS) - { - if (typeof(window.DOMParser) === 'function') - { - var domparser = new DOMParser(); - responseXML = domparser.parseFromString(this.ajaxRequest.responseText, 'text/xml'); - } else { - var div = document.createElement('div'); - div.innerHTML = this.ajaxRequest.responseText; - responseXML = div; - } - } - - var textureUrl = this.baseUrl + responseXML.getElementsByTagName('page')[0].getAttribute('file'); - var image = new ImageLoader(textureUrl, this.crossorigin); - this.texture = image.texture.baseTexture; - - var data = {}; - var info = responseXML.getElementsByTagName('info')[0]; - var common = responseXML.getElementsByTagName('common')[0]; - data.font = info.getAttribute('face'); - data.size = parseInt(info.getAttribute('size'), 10); - data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); - data.chars = {}; - - //parse letters - var letters = responseXML.getElementsByTagName('char'); - - for (var i = 0; i < letters.length; i++) - { - var charCode = parseInt(letters[i].getAttribute('id'), 10); - - var textureRect = new core.math.Rectangle( - parseInt(letters[i].getAttribute('x'), 10), - parseInt(letters[i].getAttribute('y'), 10), - parseInt(letters[i].getAttribute('width'), 10), - parseInt(letters[i].getAttribute('height'), 10) - ); - - data.chars[charCode] = { - xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), - yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), - xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), - kerning: {}, - texture: core.utils.TextureCache[charCode] = new core.Texture(this.texture, textureRect) - - }; - } - - //parse kernings - var kernings = responseXML.getElementsByTagName('kerning'); - for (i = 0; i < kernings.length; i++) - { - var first = parseInt(kernings[i].getAttribute('first'), 10); - var second = parseInt(kernings[i].getAttribute('second'), 10); - var amount = parseInt(kernings[i].getAttribute('amount'), 10); - - data.chars[second].kerning[first] = amount; - - } - - core.BitmapText.fonts[data.font] = data; - - image.addEventListener('loaded', this.onLoaded.bind(this)); - image.load(); - } - } -}; - -/** - * Invoked when all files are loaded (xml/fnt and texture) - * - * @private - */ -BitmapFontLoader.prototype.onLoaded = function () -{ - this.emit('loaded', { content: this }); -}; diff --git a/src/loaders/SpineTextureLoader.js b/src/loaders/SpineTextureLoader.js deleted file mode 100644 index c09a548..0000000 --- a/src/loaders/SpineTextureLoader.js +++ /dev/null @@ -1,56 +0,0 @@ -var core = require('../core'); - -/** - * Supporting class to load images from spine atlases as per spine spec. - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @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 - */ -function SpineTextureLoader(basePath, crossorigin) -{ - this.basePath = basePath; - this.crossorigin = crossorigin; - this.loadingCount = 0; -} - -SpineTextureLoader.prototype.constructor = SpineTextureLoader; -module.exports = SpineTextureLoader; - -core.utils.eventTarget.mixin(SpineTextureLoader.prototype); - -/** - * Starts loading a base texture as per spine specification - * - * @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 - */ -SpineTextureLoader.prototype.load = function (page, file) -{ - page.rendererObject = core.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 - * - * @param texture {BaseTexture} Texture object to destroy - */ -SpineTextureLoader.prototype.unload = function (texture) -{ - texture.destroy(true); -}; diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js new file mode 100644 index 0000000..6320ae4 --- /dev/null +++ b/src/loaders/bitmapFontParser.js @@ -0,0 +1,88 @@ +var Resource = require('asset-loader').Resource, + core = require('../core'); + +module.exports = function () +{ + return function (resource, next) + { + if (!resource.data || navigator.isCocoonJS) + { + if (window.DOMParser) + { + var domparser = new DOMParser(); + resource.data = domparser.parseFromString(this.xhr.responseText, 'text/xml'); + } + else + { + var div = document.createElement('div'); + div.innerHTML = this.xhr.responseText; + resource.data = div; + } + } + + // skip if no data + if (!resource.data) + { + return next(); + } + + var textureUrl = this.baseUrl + resource.data.getElementsByTagName('page')[0].getAttribute('file'); + var loadOptions = { + crossOrigin: resource.crossOrigin, + loadType: Resource.LOAD_TYPE.IMAGE + }; + + // load the texture for the font + this.loadResource(new Resource(textureUrl, loadOptions), function (res) + { + var data = {}; + var info = resource.data.getElementsByTagName('info')[0]; + var common = resource.data.getElementsByTagName('common')[0]; + + data.font = info.getAttribute('face'); + data.size = parseInt(info.getAttribute('size'), 10); + data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); + data.chars = {}; + + //parse letters + var letters = resource.data.getElementsByTagName('char'); + + for (var i = 0; i < letters.length; i++) + { + var charCode = parseInt(letters[i].getAttribute('id'), 10); + + var textureRect = new core.math.Rectangle( + parseInt(letters[i].getAttribute('x'), 10), + parseInt(letters[i].getAttribute('y'), 10), + parseInt(letters[i].getAttribute('width'), 10), + parseInt(letters[i].getAttribute('height'), 10) + ); + + data.chars[charCode] = { + xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), + yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), + xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), + kerning: {}, + texture: core.utils.TextureCache[charCode] = new core.Texture(res.texture.baseTexture, textureRect) + + }; + } + + //parse kernings + var kernings = resource.data.getElementsByTagName('kerning'); + for (i = 0; i < kernings.length; i++) + { + var first = parseInt(kernings[i].getAttribute('first'), 10); + var second = parseInt(kernings[i].getAttribute('second'), 10); + var amount = parseInt(kernings[i].getAttribute('amount'), 10); + + data.chars[second].kerning[first] = amount; + + } + + resource.bitmapFont = data; + + next(); + }); + }; +}; diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 4c6e1b1..a9ba61b 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,16 +1,27 @@ var Loader = require('asset-loader'), textureParser = require('./textureParser'), spritesheetParser = require('./spritesheetParser'), + spineAtlasParser = require('./spineAtlasParser'), + bitmapFontParser = require('./bitmapFontParser'), loader = new Loader(); loader // parse any json strings into objects .use(Loader.middleware.parsing.json()) + // parse any blob into more usable objects (e.g. Image) .use(Loader.middleware.parsing.json()) + // parse any Image objects into textures .use(textureParser()) + // parse any spritesheet data into multiple textures - .use(spritesheetParser()); + .use(spritesheetParser()) + + // parse any spine data into a spine object + .use(spineAtlasParser()) + + // parse any spritesheet data into multiple textures + .use(bitmapFontParser()); module.exports = loader; diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AtlasLoader.js b/src/loaders/AtlasLoader.js deleted file mode 100644 index b46e7f1..0000000 --- a/src/loaders/AtlasLoader.js +++ /dev/null @@ -1,217 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The atlas file loader is used to load in Texture Atlas data and parse it. When loaded this class will dispatch a 'loaded' event. If loading fails this class will dispatch an 'error' event. - * - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format. - * - * It is highly recommended to use texture atlases (also know as 'sprite sheets') as it allowed sprites to be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though Texture.fromFrameId() and Sprite.fromFrameId() - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AtlasLoader(url, crossorigin) -{ - this.url = url; - this.baseUrl = url.replace(/[^\/]*$/, ''); - this.crossorigin = crossorigin; - this.loaded = false; -} - -AtlasLoader.prototype.constructor = AtlasLoader; -module.exports = AtlasLoader; - -core.utils.eventTarget.mixin(AtlasLoader.prototype); - - /** - * Starts loading the JSON file - * - */ -AtlasLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onAtlasLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/json'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the Atlas has fully loaded. Parses the JSON and builds the texture frames. - * - * @private - */ -AtlasLoader.prototype.onAtlasLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.href.indexOf('http') === -1) - { - this.atlas = { - meta : { - image : [] - }, - frames : [] - }; - var result = this.ajaxRequest.responseText.split(/\r?\n/); - var lineCount = -3; - - var currentImageId = 0; - var currentFrame = null; - var nameInNextLine = false; - - var i = 0, - j = 0, - selfOnLoaded = this.onLoaded.bind(this); - - // parser without rotation support yet! - for (i = 0; i < result.length; i++) - { - result[i] = result[i].replace(/^\s+|\s+$/g, ''); - - if (result[i] === '') - { - nameInNextLine = i+1; - } - - if (result[i].length > 0) - { - if (nameInNextLine === i) - { - this.atlas.meta.image.push(result[i]); - currentImageId = this.atlas.meta.image.length - 1; - this.atlas.frames.push({}); - lineCount = -3; - } else if (lineCount > 0) - { - if (lineCount % 7 === 1) - { // frame name - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - currentFrame = { name: result[i], frame : {} }; - } else { - var text = result[i].split(' '); - if (lineCount % 7 === 3) - { // position - currentFrame.frame.x = Number(text[1].replace(',', '')); - currentFrame.frame.y = Number(text[2]); - } else if (lineCount % 7 === 4) - { // size - currentFrame.frame.w = Number(text[1].replace(',', '')); - currentFrame.frame.h = Number(text[2]); - } else if (lineCount % 7 === 5) - { // real size - var realSize = { - x : 0, - y : 0, - w : Number(text[1].replace(',', '')), - h : Number(text[2]) - }; - - if (realSize.w > currentFrame.frame.w || realSize.h > currentFrame.frame.h) - { - currentFrame.trimmed = true; - currentFrame.realSize = realSize; - } else { - currentFrame.trimmed = false; - } - } - } - } - lineCount++; - } - } - - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - - if (this.atlas.meta.image.length > 0) - { - this.images = []; - for (j = 0; j < this.atlas.meta.image.length; j++) - { - // sprite sheet - var textureUrl = this.baseUrl + this.atlas.meta.image[j]; - var frameData = this.atlas.frames[j]; - this.images.push(new ImageLoader(textureUrl, this.crossorigin)); - - for (i in frameData) - { - var rect = frameData[i].frame; - if (rect) - { - core.utils.TextureCache[i] = new core.Texture(this.images[j].texture.baseTexture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) - { - core.utils.TextureCache[i].realSize = frameData[i].realSize; - // trim in pixi not supported yet, todo update trim properties if it is done ... - core.utils.TextureCache[i].trim.x = 0; - core.utils.TextureCache[i].trim.y = 0; - } - } - } - } - - this.currentImageId = 0; - for (j = 0; j < this.images.length; j++) - { - this.images[j].on('loaded', selfOnLoaded); - } - this.images[this.currentImageId].load(); - - } else { - this.onLoaded(); - } - - } else { - this.onError(); - } - } -}; - -/** - * Invoked when json file has loaded. - * - * @private - */ -AtlasLoader.prototype.onLoaded = function () -{ - if (this.images.length - 1 > this.currentImageId) - { - this.currentImageId++; - this.images[this.currentImageId].load(); - } else { - this.loaded = true; - this.emit('loaded', { content: this }); - } -}; - -/** - * Invoked when an error occurs. - * - * @private - */ -AtlasLoader.prototype.onError = function () -{ - this.emit('error', { content: this }); -}; diff --git a/src/loaders/BitmapFontLoader.js b/src/loaders/BitmapFontLoader.js deleted file mode 100644 index 13e5c1b..0000000 --- a/src/loaders/BitmapFontLoader.js +++ /dev/null @@ -1,162 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The xml loader is used to load in XML bitmap font data ('xml' or 'fnt') - * To generate the data you can use http://www.angelcode.com/products/bmfont/ - * This loader will also load the image file as the data. - * When loaded this class will dispatch a 'loaded' event - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function BitmapFontLoader(url, crossorigin) -{ - /** - * The url of the bitmap font data - * - * @member {String} - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * The base url of the bitmap font data - * - * @member {String} - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ''); - - /** - * The texture of the bitmap font - * - * @member {Texture} - */ - this.texture = null; -} - -// constructor -BitmapFontLoader.prototype.constructor = BitmapFontLoader; -module.exports = BitmapFontLoader; - -core.utils.eventTarget.mixin(BitmapFontLoader.prototype); - -/** - * Loads the XML font data - * - */ -BitmapFontLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onXMLLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/xml'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the XML file is loaded, parses the data. - * - * @private - */ -BitmapFontLoader.prototype.onXMLLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.protocol.indexOf('http') === -1) - { - var responseXML = this.ajaxRequest.responseXML; - if (!responseXML || /MSIE 9/i.test(navigator.userAgent) || navigator.isCocoonJS) - { - if (typeof(window.DOMParser) === 'function') - { - var domparser = new DOMParser(); - responseXML = domparser.parseFromString(this.ajaxRequest.responseText, 'text/xml'); - } else { - var div = document.createElement('div'); - div.innerHTML = this.ajaxRequest.responseText; - responseXML = div; - } - } - - var textureUrl = this.baseUrl + responseXML.getElementsByTagName('page')[0].getAttribute('file'); - var image = new ImageLoader(textureUrl, this.crossorigin); - this.texture = image.texture.baseTexture; - - var data = {}; - var info = responseXML.getElementsByTagName('info')[0]; - var common = responseXML.getElementsByTagName('common')[0]; - data.font = info.getAttribute('face'); - data.size = parseInt(info.getAttribute('size'), 10); - data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); - data.chars = {}; - - //parse letters - var letters = responseXML.getElementsByTagName('char'); - - for (var i = 0; i < letters.length; i++) - { - var charCode = parseInt(letters[i].getAttribute('id'), 10); - - var textureRect = new core.math.Rectangle( - parseInt(letters[i].getAttribute('x'), 10), - parseInt(letters[i].getAttribute('y'), 10), - parseInt(letters[i].getAttribute('width'), 10), - parseInt(letters[i].getAttribute('height'), 10) - ); - - data.chars[charCode] = { - xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), - yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), - xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), - kerning: {}, - texture: core.utils.TextureCache[charCode] = new core.Texture(this.texture, textureRect) - - }; - } - - //parse kernings - var kernings = responseXML.getElementsByTagName('kerning'); - for (i = 0; i < kernings.length; i++) - { - var first = parseInt(kernings[i].getAttribute('first'), 10); - var second = parseInt(kernings[i].getAttribute('second'), 10); - var amount = parseInt(kernings[i].getAttribute('amount'), 10); - - data.chars[second].kerning[first] = amount; - - } - - core.BitmapText.fonts[data.font] = data; - - image.addEventListener('loaded', this.onLoaded.bind(this)); - image.load(); - } - } -}; - -/** - * Invoked when all files are loaded (xml/fnt and texture) - * - * @private - */ -BitmapFontLoader.prototype.onLoaded = function () -{ - this.emit('loaded', { content: this }); -}; diff --git a/src/loaders/SpineTextureLoader.js b/src/loaders/SpineTextureLoader.js deleted file mode 100644 index c09a548..0000000 --- a/src/loaders/SpineTextureLoader.js +++ /dev/null @@ -1,56 +0,0 @@ -var core = require('../core'); - -/** - * Supporting class to load images from spine atlases as per spine spec. - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @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 - */ -function SpineTextureLoader(basePath, crossorigin) -{ - this.basePath = basePath; - this.crossorigin = crossorigin; - this.loadingCount = 0; -} - -SpineTextureLoader.prototype.constructor = SpineTextureLoader; -module.exports = SpineTextureLoader; - -core.utils.eventTarget.mixin(SpineTextureLoader.prototype); - -/** - * Starts loading a base texture as per spine specification - * - * @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 - */ -SpineTextureLoader.prototype.load = function (page, file) -{ - page.rendererObject = core.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 - * - * @param texture {BaseTexture} Texture object to destroy - */ -SpineTextureLoader.prototype.unload = function (texture) -{ - texture.destroy(true); -}; diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js new file mode 100644 index 0000000..6320ae4 --- /dev/null +++ b/src/loaders/bitmapFontParser.js @@ -0,0 +1,88 @@ +var Resource = require('asset-loader').Resource, + core = require('../core'); + +module.exports = function () +{ + return function (resource, next) + { + if (!resource.data || navigator.isCocoonJS) + { + if (window.DOMParser) + { + var domparser = new DOMParser(); + resource.data = domparser.parseFromString(this.xhr.responseText, 'text/xml'); + } + else + { + var div = document.createElement('div'); + div.innerHTML = this.xhr.responseText; + resource.data = div; + } + } + + // skip if no data + if (!resource.data) + { + return next(); + } + + var textureUrl = this.baseUrl + resource.data.getElementsByTagName('page')[0].getAttribute('file'); + var loadOptions = { + crossOrigin: resource.crossOrigin, + loadType: Resource.LOAD_TYPE.IMAGE + }; + + // load the texture for the font + this.loadResource(new Resource(textureUrl, loadOptions), function (res) + { + var data = {}; + var info = resource.data.getElementsByTagName('info')[0]; + var common = resource.data.getElementsByTagName('common')[0]; + + data.font = info.getAttribute('face'); + data.size = parseInt(info.getAttribute('size'), 10); + data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); + data.chars = {}; + + //parse letters + var letters = resource.data.getElementsByTagName('char'); + + for (var i = 0; i < letters.length; i++) + { + var charCode = parseInt(letters[i].getAttribute('id'), 10); + + var textureRect = new core.math.Rectangle( + parseInt(letters[i].getAttribute('x'), 10), + parseInt(letters[i].getAttribute('y'), 10), + parseInt(letters[i].getAttribute('width'), 10), + parseInt(letters[i].getAttribute('height'), 10) + ); + + data.chars[charCode] = { + xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), + yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), + xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), + kerning: {}, + texture: core.utils.TextureCache[charCode] = new core.Texture(res.texture.baseTexture, textureRect) + + }; + } + + //parse kernings + var kernings = resource.data.getElementsByTagName('kerning'); + for (i = 0; i < kernings.length; i++) + { + var first = parseInt(kernings[i].getAttribute('first'), 10); + var second = parseInt(kernings[i].getAttribute('second'), 10); + var amount = parseInt(kernings[i].getAttribute('amount'), 10); + + data.chars[second].kerning[first] = amount; + + } + + resource.bitmapFont = data; + + next(); + }); + }; +}; diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 4c6e1b1..a9ba61b 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,16 +1,27 @@ var Loader = require('asset-loader'), textureParser = require('./textureParser'), spritesheetParser = require('./spritesheetParser'), + spineAtlasParser = require('./spineAtlasParser'), + bitmapFontParser = require('./bitmapFontParser'), loader = new Loader(); loader // parse any json strings into objects .use(Loader.middleware.parsing.json()) + // parse any blob into more usable objects (e.g. Image) .use(Loader.middleware.parsing.json()) + // parse any Image objects into textures .use(textureParser()) + // parse any spritesheet data into multiple textures - .use(spritesheetParser()); + .use(spritesheetParser()) + + // parse any spine data into a spine object + .use(spineAtlasParser()) + + // parse any spritesheet data into multiple textures + .use(bitmapFontParser()); module.exports = loader; diff --git a/src/loaders/spineAtlasParser.js b/src/loaders/spineAtlasParser.js index 85849f2..877888c 100644 --- a/src/loaders/spineAtlasParser.js +++ b/src/loaders/spineAtlasParser.js @@ -1,5 +1,5 @@ var Resource = require('asset-loader').Resource, - core = require('../core'), + async = require('async'), spine = require('../spine'); module.exports = function () @@ -15,51 +15,38 @@ * have the same name */ var atlasPath = resource.url.substr(0, resource.url.lastIndexOf('.')) + '.atlas'; - var atlasOptions = { crossOrigin: resource.crossOrigin, xhrType: Resource.XHR_RESPONSE_TYPE.TEXT }; + var atlasOptions = { + crossOrigin: resource.crossOrigin, + xhrType: Resource.XHR_RESPONSE_TYPE.TEXT + }; - this.loadResource(new Resource(atlasPath, atlasOptions), function (res) { - ///////////////////////////////////////////////// - // TODO: THIS IS OLD STYLE - - - // create a new instance of a spine texture loader for this spine object // - var textureLoader = new SpineTextureLoader(this.url.substring(0, this.url.lastIndexOf('/'))); - - // create a spine atlas using the loaded text and a spine texture loader instance // - var spineAtlas = new spine.Atlas(this.ajaxRequest.responseText, textureLoader); - - // now we use an atlas attachment loader // - var attachmentLoader = new spine.AtlasAttachmentLoader(spineAtlas); + this.loadResource(new Resource(atlasPath, atlasOptions), function (res) + { + // create a spine atlas using the loaded text + var spineAtlas = new spine.Atlas(this.ajaxRequest.responseText, this.baseUrl, res.crossOrigin); // spine animation - var spineJsonParser = new spine.SkeletonJson(attachmentLoader); - var skeletonData = spineJsonParser.readSkeletonData(originalLoader.json); + var spineJsonParser = new spine.SkeletonJsonParser(new spine.AtlasAttachmentParser(spineAtlas)); + var skeletonData = spineJsonParser.readSkeletonData(resource.data); - core.utils.AnimCache[originalLoader.url] = skeletonData; - originalLoader.spine = skeletonData; - originalLoader.spineAtlas = spineAtlas; - originalLoader.spineAtlasLoader = atlasLoader; + // core.utils.AnimCache[originalLoader.url] = skeletonData; - // wait for textures to finish loading if needed - if (textureLoader.loadingCount > 0) + resource.spine = skeletonData; + resource.spineAtlas = spineAtlas; + + // Go through each spineAtlas.pages and wait for page.rendererObject (a baseTexture) to + // load. Once all loaded, then call the next function. + async.each(spineAtlas.pages, function (page, done) { - textureLoader.addEventListener('loadedBaseTexture', function (evt) + if (page.rendererObject.hasLoaded) { - if (evt.content.content.loadingCount <= 0) - { - originalLoader.onLoaded(); - } - }); - } - else - { - originalLoader.onLoaded(); - } - - - ///////////////////////////////////////////////// - - next(); + done(); + } + else + { + page.rendererObject.once('loaded', done); + } + }, next); }); } else { diff --git a/src/loaders/AssetLoader.js b/src/loaders/AssetLoader.js deleted file mode 100644 index c4dba1c..0000000 --- a/src/loaders/AssetLoader.js +++ /dev/null @@ -1,177 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'), - JsonLoader = require('./JsonLoader'), - AtlasLoader = require('./AtlasLoader'), - SpineLoader = require('./SpineLoader'), - BitmapFontLoader = require('./BitmapFontLoader'); - -/** - * A Class that loads a bunch of images / sprite sheet / bitmap font files. Once the - * assets have been loaded they are added to the PIXI Texture cache and can be accessed - * easily through Texture.fromImage() and Sprite.fromImage() - * When all items have been loaded this class will dispatch a 'onLoaded' event - * As each individual item is loaded this class will dispatch a 'onProgress' event - * - * @class - * @namespace PIXI - * @mixes eventTarget - * @param assetURLs {string[]} An array of image/sprite sheet urls that you would like loaded - * supported. Supported image formats include 'jpeg', 'jpg', 'png', 'gif'. Supported - * sprite sheet data formats only include 'JSON' at this time. Supported bitmap font - * data formats include 'xml' and 'fnt'. - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AssetLoader(assetURLs, crossorigin) -{ - /** - * The array of asset URLs that are going to be loaded - * - * @member {string[]} - */ - this.assetURLs = assetURLs; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * Maps file extension to loader types - * - * @member {object} - */ - this.loadersByType = { - 'jpg': ImageLoader, - 'jpeg': ImageLoader, - 'png': ImageLoader, - 'gif': ImageLoader, - 'webp': ImageLoader, - 'json': JsonLoader, - 'atlas': AtlasLoader, - 'anim': SpineLoader, - 'xml': BitmapFontLoader, - 'fnt': BitmapFontLoader - }; -} - -// constructor -AssetLoader.prototype.constructor = AssetLoader; -module.exports = AssetLoader; - -core.utils.eventTarget.mixin(AssetLoader.prototype); - -/** - * Fired when an item has loaded - * @event onProgress - */ - -/** - * Fired when all the assets have loaded - * @event onComplete - */ - -/** - * Given a filename, returns its extension. - * - * @param str {string} the name of the asset - */ -AssetLoader.prototype._getDataType = function (str) -{ - var test = 'data:'; - var start = str.slice(0, test.length).toLowerCase(); - - if (start === test) - { - var data = str.slice(test.length); - var sepIdx = data.indexOf(','); - - // check for malformed data URI scheme - if (sepIdx === -1) - { - return null; - } - - //e.g. 'image/gif;base64' => 'image/gif' - var info = data.slice(0, sepIdx).split(';')[0]; - - //We might need to handle some special cases here... - //standardize text/plain to 'txt' file extension - if (!info || info.toLowerCase() === 'text/plain') - { - return 'txt'; - } - - //User specified mime type, try splitting it by '/' - return info.split('/').pop().toLowerCase(); - } - - return null; -}; - -/** - * Starts loading the assets sequentially - * - */ -AssetLoader.prototype.load = function () -{ - var scope = this; - - function onLoad(evt) - { - scope.onAssetLoaded(evt.data.content); - } - - this.loadCount = this.assetURLs.length; - - for (var i=0; i < this.assetURLs.length; i++) - { - var fileName = this.assetURLs[i]; - //first see if we have a data URI scheme.. - var fileType = this._getDataType(fileName); - - //if not, assume it's a file URI - if (!fileType) - { - fileType = fileName.split('?').shift().split('.').pop().toLowerCase(); - } - - var Constructor = this.loadersByType[fileType]; - if (!Constructor) - { - throw new Error(fileType + ' is an unsupported file type'); - } - - var loader = new Constructor(fileName, this.crossorigin); - - loader.on('loaded', onLoad); - loader.load(); - } -}; - -/** - * Invoked after each file is loaded - * - * @private - */ -AssetLoader.prototype.onAssetLoaded = function (loader) -{ - this.loadCount--; - this.emit('onProgress', { content: this, loader: loader }); - - if (this.onProgress) - { - this.onProgress(loader); - } - - if (!this.loadCount) - { - this.emit('onComplete', { content: this }); - - if (this.onComplete) - { - this.onComplete(); - } - } -}; diff --git a/src/loaders/AtlasLoader.js b/src/loaders/AtlasLoader.js deleted file mode 100644 index b46e7f1..0000000 --- a/src/loaders/AtlasLoader.js +++ /dev/null @@ -1,217 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The atlas file loader is used to load in Texture Atlas data and parse it. When loaded this class will dispatch a 'loaded' event. If loading fails this class will dispatch an 'error' event. - * - * To generate the data you can use http://www.codeandweb.com/texturepacker and publish in the 'JSON' format. - * - * It is highly recommended to use texture atlases (also know as 'sprite sheets') as it allowed sprites to be batched and drawn together for highly increased rendering speed. - * Once the data has been loaded the frames are stored in the PIXI texture cache and can be accessed though Texture.fromFrameId() and Sprite.fromFrameId() - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function AtlasLoader(url, crossorigin) -{ - this.url = url; - this.baseUrl = url.replace(/[^\/]*$/, ''); - this.crossorigin = crossorigin; - this.loaded = false; -} - -AtlasLoader.prototype.constructor = AtlasLoader; -module.exports = AtlasLoader; - -core.utils.eventTarget.mixin(AtlasLoader.prototype); - - /** - * Starts loading the JSON file - * - */ -AtlasLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onAtlasLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/json'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the Atlas has fully loaded. Parses the JSON and builds the texture frames. - * - * @private - */ -AtlasLoader.prototype.onAtlasLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.href.indexOf('http') === -1) - { - this.atlas = { - meta : { - image : [] - }, - frames : [] - }; - var result = this.ajaxRequest.responseText.split(/\r?\n/); - var lineCount = -3; - - var currentImageId = 0; - var currentFrame = null; - var nameInNextLine = false; - - var i = 0, - j = 0, - selfOnLoaded = this.onLoaded.bind(this); - - // parser without rotation support yet! - for (i = 0; i < result.length; i++) - { - result[i] = result[i].replace(/^\s+|\s+$/g, ''); - - if (result[i] === '') - { - nameInNextLine = i+1; - } - - if (result[i].length > 0) - { - if (nameInNextLine === i) - { - this.atlas.meta.image.push(result[i]); - currentImageId = this.atlas.meta.image.length - 1; - this.atlas.frames.push({}); - lineCount = -3; - } else if (lineCount > 0) - { - if (lineCount % 7 === 1) - { // frame name - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - currentFrame = { name: result[i], frame : {} }; - } else { - var text = result[i].split(' '); - if (lineCount % 7 === 3) - { // position - currentFrame.frame.x = Number(text[1].replace(',', '')); - currentFrame.frame.y = Number(text[2]); - } else if (lineCount % 7 === 4) - { // size - currentFrame.frame.w = Number(text[1].replace(',', '')); - currentFrame.frame.h = Number(text[2]); - } else if (lineCount % 7 === 5) - { // real size - var realSize = { - x : 0, - y : 0, - w : Number(text[1].replace(',', '')), - h : Number(text[2]) - }; - - if (realSize.w > currentFrame.frame.w || realSize.h > currentFrame.frame.h) - { - currentFrame.trimmed = true; - currentFrame.realSize = realSize; - } else { - currentFrame.trimmed = false; - } - } - } - } - lineCount++; - } - } - - if (currentFrame) - { - this.atlas.frames[currentImageId][currentFrame.name] = currentFrame; - } - - if (this.atlas.meta.image.length > 0) - { - this.images = []; - for (j = 0; j < this.atlas.meta.image.length; j++) - { - // sprite sheet - var textureUrl = this.baseUrl + this.atlas.meta.image[j]; - var frameData = this.atlas.frames[j]; - this.images.push(new ImageLoader(textureUrl, this.crossorigin)); - - for (i in frameData) - { - var rect = frameData[i].frame; - if (rect) - { - core.utils.TextureCache[i] = new core.Texture(this.images[j].texture.baseTexture, { - x: rect.x, - y: rect.y, - width: rect.w, - height: rect.h - }); - if (frameData[i].trimmed) - { - core.utils.TextureCache[i].realSize = frameData[i].realSize; - // trim in pixi not supported yet, todo update trim properties if it is done ... - core.utils.TextureCache[i].trim.x = 0; - core.utils.TextureCache[i].trim.y = 0; - } - } - } - } - - this.currentImageId = 0; - for (j = 0; j < this.images.length; j++) - { - this.images[j].on('loaded', selfOnLoaded); - } - this.images[this.currentImageId].load(); - - } else { - this.onLoaded(); - } - - } else { - this.onError(); - } - } -}; - -/** - * Invoked when json file has loaded. - * - * @private - */ -AtlasLoader.prototype.onLoaded = function () -{ - if (this.images.length - 1 > this.currentImageId) - { - this.currentImageId++; - this.images[this.currentImageId].load(); - } else { - this.loaded = true; - this.emit('loaded', { content: this }); - } -}; - -/** - * Invoked when an error occurs. - * - * @private - */ -AtlasLoader.prototype.onError = function () -{ - this.emit('error', { content: this }); -}; diff --git a/src/loaders/BitmapFontLoader.js b/src/loaders/BitmapFontLoader.js deleted file mode 100644 index 13e5c1b..0000000 --- a/src/loaders/BitmapFontLoader.js +++ /dev/null @@ -1,162 +0,0 @@ -var core = require('../core'), - ImageLoader = require('./ImageLoader'); - -/** - * The xml loader is used to load in XML bitmap font data ('xml' or 'fnt') - * To generate the data you can use http://www.angelcode.com/products/bmfont/ - * This loader will also load the image file as the data. - * When loaded this class will dispatch a 'loaded' event - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @param url {String} The url of the sprite sheet JSON file - * @param crossorigin {boolean} Whether requests should be treated as crossorigin - */ -function BitmapFontLoader(url, crossorigin) -{ - /** - * The url of the bitmap font data - * - * @member {String} - */ - this.url = url; - - /** - * Whether the requests should be treated as cross origin - * - * @member {boolean} - */ - this.crossorigin = crossorigin; - - /** - * The base url of the bitmap font data - * - * @member {String} - * @readOnly - */ - this.baseUrl = url.replace(/[^\/]*$/, ''); - - /** - * The texture of the bitmap font - * - * @member {Texture} - */ - this.texture = null; -} - -// constructor -BitmapFontLoader.prototype.constructor = BitmapFontLoader; -module.exports = BitmapFontLoader; - -core.utils.eventTarget.mixin(BitmapFontLoader.prototype); - -/** - * Loads the XML font data - * - */ -BitmapFontLoader.prototype.load = function () -{ - this.ajaxRequest = new core.utils.AjaxRequest(); - this.ajaxRequest.onreadystatechange = this.onXMLLoaded.bind(this); - - this.ajaxRequest.open('GET', this.url, true); - - if (this.ajaxRequest.overrideMimeType) - { - this.ajaxRequest.overrideMimeType('application/xml'); - } - - this.ajaxRequest.send(null); -}; - -/** - * Invoked when the XML file is loaded, parses the data. - * - * @private - */ -BitmapFontLoader.prototype.onXMLLoaded = function () -{ - if (this.ajaxRequest.readyState === 4) - { - if (this.ajaxRequest.status === 200 || window.location.protocol.indexOf('http') === -1) - { - var responseXML = this.ajaxRequest.responseXML; - if (!responseXML || /MSIE 9/i.test(navigator.userAgent) || navigator.isCocoonJS) - { - if (typeof(window.DOMParser) === 'function') - { - var domparser = new DOMParser(); - responseXML = domparser.parseFromString(this.ajaxRequest.responseText, 'text/xml'); - } else { - var div = document.createElement('div'); - div.innerHTML = this.ajaxRequest.responseText; - responseXML = div; - } - } - - var textureUrl = this.baseUrl + responseXML.getElementsByTagName('page')[0].getAttribute('file'); - var image = new ImageLoader(textureUrl, this.crossorigin); - this.texture = image.texture.baseTexture; - - var data = {}; - var info = responseXML.getElementsByTagName('info')[0]; - var common = responseXML.getElementsByTagName('common')[0]; - data.font = info.getAttribute('face'); - data.size = parseInt(info.getAttribute('size'), 10); - data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); - data.chars = {}; - - //parse letters - var letters = responseXML.getElementsByTagName('char'); - - for (var i = 0; i < letters.length; i++) - { - var charCode = parseInt(letters[i].getAttribute('id'), 10); - - var textureRect = new core.math.Rectangle( - parseInt(letters[i].getAttribute('x'), 10), - parseInt(letters[i].getAttribute('y'), 10), - parseInt(letters[i].getAttribute('width'), 10), - parseInt(letters[i].getAttribute('height'), 10) - ); - - data.chars[charCode] = { - xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), - yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), - xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), - kerning: {}, - texture: core.utils.TextureCache[charCode] = new core.Texture(this.texture, textureRect) - - }; - } - - //parse kernings - var kernings = responseXML.getElementsByTagName('kerning'); - for (i = 0; i < kernings.length; i++) - { - var first = parseInt(kernings[i].getAttribute('first'), 10); - var second = parseInt(kernings[i].getAttribute('second'), 10); - var amount = parseInt(kernings[i].getAttribute('amount'), 10); - - data.chars[second].kerning[first] = amount; - - } - - core.BitmapText.fonts[data.font] = data; - - image.addEventListener('loaded', this.onLoaded.bind(this)); - image.load(); - } - } -}; - -/** - * Invoked when all files are loaded (xml/fnt and texture) - * - * @private - */ -BitmapFontLoader.prototype.onLoaded = function () -{ - this.emit('loaded', { content: this }); -}; diff --git a/src/loaders/SpineTextureLoader.js b/src/loaders/SpineTextureLoader.js deleted file mode 100644 index c09a548..0000000 --- a/src/loaders/SpineTextureLoader.js +++ /dev/null @@ -1,56 +0,0 @@ -var core = require('../core'); - -/** - * Supporting class to load images from spine atlases as per spine spec. - * - * @class - * @mixes eventTarget - * @namespace PIXI - * @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 - */ -function SpineTextureLoader(basePath, crossorigin) -{ - this.basePath = basePath; - this.crossorigin = crossorigin; - this.loadingCount = 0; -} - -SpineTextureLoader.prototype.constructor = SpineTextureLoader; -module.exports = SpineTextureLoader; - -core.utils.eventTarget.mixin(SpineTextureLoader.prototype); - -/** - * Starts loading a base texture as per spine specification - * - * @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 - */ -SpineTextureLoader.prototype.load = function (page, file) -{ - page.rendererObject = core.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 - * - * @param texture {BaseTexture} Texture object to destroy - */ -SpineTextureLoader.prototype.unload = function (texture) -{ - texture.destroy(true); -}; diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js new file mode 100644 index 0000000..6320ae4 --- /dev/null +++ b/src/loaders/bitmapFontParser.js @@ -0,0 +1,88 @@ +var Resource = require('asset-loader').Resource, + core = require('../core'); + +module.exports = function () +{ + return function (resource, next) + { + if (!resource.data || navigator.isCocoonJS) + { + if (window.DOMParser) + { + var domparser = new DOMParser(); + resource.data = domparser.parseFromString(this.xhr.responseText, 'text/xml'); + } + else + { + var div = document.createElement('div'); + div.innerHTML = this.xhr.responseText; + resource.data = div; + } + } + + // skip if no data + if (!resource.data) + { + return next(); + } + + var textureUrl = this.baseUrl + resource.data.getElementsByTagName('page')[0].getAttribute('file'); + var loadOptions = { + crossOrigin: resource.crossOrigin, + loadType: Resource.LOAD_TYPE.IMAGE + }; + + // load the texture for the font + this.loadResource(new Resource(textureUrl, loadOptions), function (res) + { + var data = {}; + var info = resource.data.getElementsByTagName('info')[0]; + var common = resource.data.getElementsByTagName('common')[0]; + + data.font = info.getAttribute('face'); + data.size = parseInt(info.getAttribute('size'), 10); + data.lineHeight = parseInt(common.getAttribute('lineHeight'), 10); + data.chars = {}; + + //parse letters + var letters = resource.data.getElementsByTagName('char'); + + for (var i = 0; i < letters.length; i++) + { + var charCode = parseInt(letters[i].getAttribute('id'), 10); + + var textureRect = new core.math.Rectangle( + parseInt(letters[i].getAttribute('x'), 10), + parseInt(letters[i].getAttribute('y'), 10), + parseInt(letters[i].getAttribute('width'), 10), + parseInt(letters[i].getAttribute('height'), 10) + ); + + data.chars[charCode] = { + xOffset: parseInt(letters[i].getAttribute('xoffset'), 10), + yOffset: parseInt(letters[i].getAttribute('yoffset'), 10), + xAdvance: parseInt(letters[i].getAttribute('xadvance'), 10), + kerning: {}, + texture: core.utils.TextureCache[charCode] = new core.Texture(res.texture.baseTexture, textureRect) + + }; + } + + //parse kernings + var kernings = resource.data.getElementsByTagName('kerning'); + for (i = 0; i < kernings.length; i++) + { + var first = parseInt(kernings[i].getAttribute('first'), 10); + var second = parseInt(kernings[i].getAttribute('second'), 10); + var amount = parseInt(kernings[i].getAttribute('amount'), 10); + + data.chars[second].kerning[first] = amount; + + } + + resource.bitmapFont = data; + + next(); + }); + }; +}; diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 4c6e1b1..a9ba61b 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,16 +1,27 @@ var Loader = require('asset-loader'), textureParser = require('./textureParser'), spritesheetParser = require('./spritesheetParser'), + spineAtlasParser = require('./spineAtlasParser'), + bitmapFontParser = require('./bitmapFontParser'), loader = new Loader(); loader // parse any json strings into objects .use(Loader.middleware.parsing.json()) + // parse any blob into more usable objects (e.g. Image) .use(Loader.middleware.parsing.json()) + // parse any Image objects into textures .use(textureParser()) + // parse any spritesheet data into multiple textures - .use(spritesheetParser()); + .use(spritesheetParser()) + + // parse any spine data into a spine object + .use(spineAtlasParser()) + + // parse any spritesheet data into multiple textures + .use(bitmapFontParser()); module.exports = loader; diff --git a/src/loaders/spineAtlasParser.js b/src/loaders/spineAtlasParser.js index 85849f2..877888c 100644 --- a/src/loaders/spineAtlasParser.js +++ b/src/loaders/spineAtlasParser.js @@ -1,5 +1,5 @@ var Resource = require('asset-loader').Resource, - core = require('../core'), + async = require('async'), spine = require('../spine'); module.exports = function () @@ -15,51 +15,38 @@ * have the same name */ var atlasPath = resource.url.substr(0, resource.url.lastIndexOf('.')) + '.atlas'; - var atlasOptions = { crossOrigin: resource.crossOrigin, xhrType: Resource.XHR_RESPONSE_TYPE.TEXT }; + var atlasOptions = { + crossOrigin: resource.crossOrigin, + xhrType: Resource.XHR_RESPONSE_TYPE.TEXT + }; - this.loadResource(new Resource(atlasPath, atlasOptions), function (res) { - ///////////////////////////////////////////////// - // TODO: THIS IS OLD STYLE - - - // create a new instance of a spine texture loader for this spine object // - var textureLoader = new SpineTextureLoader(this.url.substring(0, this.url.lastIndexOf('/'))); - - // create a spine atlas using the loaded text and a spine texture loader instance // - var spineAtlas = new spine.Atlas(this.ajaxRequest.responseText, textureLoader); - - // now we use an atlas attachment loader // - var attachmentLoader = new spine.AtlasAttachmentLoader(spineAtlas); + this.loadResource(new Resource(atlasPath, atlasOptions), function (res) + { + // create a spine atlas using the loaded text + var spineAtlas = new spine.Atlas(this.ajaxRequest.responseText, this.baseUrl, res.crossOrigin); // spine animation - var spineJsonParser = new spine.SkeletonJson(attachmentLoader); - var skeletonData = spineJsonParser.readSkeletonData(originalLoader.json); + var spineJsonParser = new spine.SkeletonJsonParser(new spine.AtlasAttachmentParser(spineAtlas)); + var skeletonData = spineJsonParser.readSkeletonData(resource.data); - core.utils.AnimCache[originalLoader.url] = skeletonData; - originalLoader.spine = skeletonData; - originalLoader.spineAtlas = spineAtlas; - originalLoader.spineAtlasLoader = atlasLoader; + // core.utils.AnimCache[originalLoader.url] = skeletonData; - // wait for textures to finish loading if needed - if (textureLoader.loadingCount > 0) + resource.spine = skeletonData; + resource.spineAtlas = spineAtlas; + + // Go through each spineAtlas.pages and wait for page.rendererObject (a baseTexture) to + // load. Once all loaded, then call the next function. + async.each(spineAtlas.pages, function (page, done) { - textureLoader.addEventListener('loadedBaseTexture', function (evt) + if (page.rendererObject.hasLoaded) { - if (evt.content.content.loadingCount <= 0) - { - originalLoader.onLoaded(); - } - }); - } - else - { - originalLoader.onLoaded(); - } - - - ///////////////////////////////////////////////// - - next(); + done(); + } + else + { + page.rendererObject.once('loaded', done); + } + }, next); }); } else { diff --git a/src/spine/SpineRuntime.js b/src/spine/SpineRuntime.js index fadd1b5..80789f7 100644 --- a/src/spine/SpineRuntime.js +++ b/src/spine/SpineRuntime.js @@ -27,6 +27,8 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ +var core = require('../core'); + var spine = module.exports = { radDeg: 180 / Math.PI, @@ -1905,11 +1907,11 @@ } }; -spine.SkeletonJson = function (attachmentLoader) +spine.SkeletonJsonParser = function (attachmentLoader) { this.attachmentLoader = attachmentLoader; }; -spine.SkeletonJson.prototype = { +spine.SkeletonJsonParser.prototype = { scale: 1, readSkeletonData: function (root, name) { @@ -2486,12 +2488,20 @@ } }; -spine.Atlas = function (atlasText, textureLoader) +spine.Atlas = function (atlasText, baseUrl, crossOrigin) { - this.textureLoader = textureLoader; + if (baseUrl && baseUrl.indexOf('/') !== baseUrl.length) + { + baseUrl += '/'; + } + this.pages = []; this.regions = []; + this.texturesLoading = 0; + + var self = this; + var reader = new spine.AtlasReader(atlasText); var tuple = []; tuple.length = 4; @@ -2530,7 +2540,7 @@ else if (direction == "xy") page.uWrap = page.vWrap = spine.Atlas.TextureWrap.repeat; - textureLoader.load(page, line, this); + page.rendererObject = core.BaseTexture.fromImage(baseUrl + line, crossOrigin); this.pages.push(page); @@ -2601,7 +2611,7 @@ { var pages = this.pages; for (var i = 0, n = pages.length; i < n; i++) - this.textureLoader.unload(pages[i].rendererObject); + pages[i].rendererObject.destroy(true); }, updateUVs: function (page) { @@ -2721,11 +2731,11 @@ } }; -spine.AtlasAttachmentLoader = function (atlas) +spine.AtlasAttachmentParser = function (atlas) { this.atlas = atlas; }; -spine.AtlasAttachmentLoader.prototype = { +spine.AtlasAttachmentParser.prototype = { newRegionAttachment: function (skin, name, path) { var region = this.atlas.findRegion(path);