diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/test/core/Text.js b/test/core/Text.js index 4f67752..b8ce561 100644 --- a/test/core/Text.js +++ b/test/core/Text.js @@ -2,6 +2,40 @@ describe('PIXI.Text', function () { + describe('getFontStyle', function () + { + it('should be a valid API', function () + { + expect(PIXI.Text.getFontStyle).to.be.a.function; + }); + + it('should assume pixel fonts', function () + { + const style = PIXI.Text.getFontStyle({ fontSize: 72 }); + + expect(style).to.be.a.string; + expect(style).to.have.string(' 72px '); + }); + + it('should handle multiple fonts as array', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: ['Georgia', 'Arial', 'sans-serif'], + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + + it('should handle multiple fonts as string', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: 'Georgia, "Arial", sans-serif', + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + }); + describe('destroy', function () { it('should call through to Sprite.destroy', function () diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/test/core/Text.js b/test/core/Text.js index 4f67752..b8ce561 100644 --- a/test/core/Text.js +++ b/test/core/Text.js @@ -2,6 +2,40 @@ describe('PIXI.Text', function () { + describe('getFontStyle', function () + { + it('should be a valid API', function () + { + expect(PIXI.Text.getFontStyle).to.be.a.function; + }); + + it('should assume pixel fonts', function () + { + const style = PIXI.Text.getFontStyle({ fontSize: 72 }); + + expect(style).to.be.a.string; + expect(style).to.have.string(' 72px '); + }); + + it('should handle multiple fonts as array', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: ['Georgia', 'Arial', 'sans-serif'], + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + + it('should handle multiple fonts as string', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: 'Georgia, "Arial", sans-serif', + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + }); + describe('destroy', function () { it('should call through to Sprite.destroy', function () diff --git a/test/index.js b/test/index.js index 50a85da..9689aa0 100755 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ }); require('./core'); require('./interaction'); + require('./loaders'); require('./renders'); require('./prepare'); }); diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/test/core/Text.js b/test/core/Text.js index 4f67752..b8ce561 100644 --- a/test/core/Text.js +++ b/test/core/Text.js @@ -2,6 +2,40 @@ describe('PIXI.Text', function () { + describe('getFontStyle', function () + { + it('should be a valid API', function () + { + expect(PIXI.Text.getFontStyle).to.be.a.function; + }); + + it('should assume pixel fonts', function () + { + const style = PIXI.Text.getFontStyle({ fontSize: 72 }); + + expect(style).to.be.a.string; + expect(style).to.have.string(' 72px '); + }); + + it('should handle multiple fonts as array', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: ['Georgia', 'Arial', 'sans-serif'], + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + + it('should handle multiple fonts as string', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: 'Georgia, "Arial", sans-serif', + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + }); + describe('destroy', function () { it('should call through to Sprite.destroy', function () diff --git a/test/index.js b/test/index.js index 50a85da..9689aa0 100755 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ }); require('./core'); require('./interaction'); + require('./loaders'); require('./renders'); require('./prepare'); }); diff --git a/test/loaders/bitmapFontParser.js b/test/loaders/bitmapFontParser.js new file mode 100644 index 0000000..7c77343 --- /dev/null +++ b/test/loaders/bitmapFontParser.js @@ -0,0 +1,46 @@ +'use strict'; + +describe('PIXI.loaders.bitmapFontParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.bitmapFontParser).to.be.a('function'); + expect(PIXI.loaders.bitmapFontParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not XML', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should do nothing if the resource is not properly formatted XML', function () + { + const spy = sinon.spy(); + const res = { data: document.createDocumentFragment() }; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + // TODO: Test the texture cache code path. + // TODO: Test the loading texture code path. + // TODO: Test data-url code paths. +}); + +describe('PIXI.loaders.parseBitmapFontData', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.parseBitmapFontData).to.be.a('function'); + }); + + // TODO: Test the parser code. +}); diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/test/core/Text.js b/test/core/Text.js index 4f67752..b8ce561 100644 --- a/test/core/Text.js +++ b/test/core/Text.js @@ -2,6 +2,40 @@ describe('PIXI.Text', function () { + describe('getFontStyle', function () + { + it('should be a valid API', function () + { + expect(PIXI.Text.getFontStyle).to.be.a.function; + }); + + it('should assume pixel fonts', function () + { + const style = PIXI.Text.getFontStyle({ fontSize: 72 }); + + expect(style).to.be.a.string; + expect(style).to.have.string(' 72px '); + }); + + it('should handle multiple fonts as array', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: ['Georgia', 'Arial', 'sans-serif'], + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + + it('should handle multiple fonts as string', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: 'Georgia, "Arial", sans-serif', + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + }); + describe('destroy', function () { it('should call through to Sprite.destroy', function () diff --git a/test/index.js b/test/index.js index 50a85da..9689aa0 100755 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ }); require('./core'); require('./interaction'); + require('./loaders'); require('./renders'); require('./prepare'); }); diff --git a/test/loaders/bitmapFontParser.js b/test/loaders/bitmapFontParser.js new file mode 100644 index 0000000..7c77343 --- /dev/null +++ b/test/loaders/bitmapFontParser.js @@ -0,0 +1,46 @@ +'use strict'; + +describe('PIXI.loaders.bitmapFontParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.bitmapFontParser).to.be.a('function'); + expect(PIXI.loaders.bitmapFontParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not XML', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should do nothing if the resource is not properly formatted XML', function () + { + const spy = sinon.spy(); + const res = { data: document.createDocumentFragment() }; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + // TODO: Test the texture cache code path. + // TODO: Test the loading texture code path. + // TODO: Test data-url code paths. +}); + +describe('PIXI.loaders.parseBitmapFontData', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.parseBitmapFontData).to.be.a('function'); + }); + + // TODO: Test the parser code. +}); diff --git a/test/loaders/index.js b/test/loaders/index.js new file mode 100644 index 0000000..97fc849 --- /dev/null +++ b/test/loaders/index.js @@ -0,0 +1,6 @@ +'use strict'; + +require('./bitmapFontParser'); +require('./loader'); +require('./spritesheetParser'); +require('./textureParser'); diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/test/core/Text.js b/test/core/Text.js index 4f67752..b8ce561 100644 --- a/test/core/Text.js +++ b/test/core/Text.js @@ -2,6 +2,40 @@ describe('PIXI.Text', function () { + describe('getFontStyle', function () + { + it('should be a valid API', function () + { + expect(PIXI.Text.getFontStyle).to.be.a.function; + }); + + it('should assume pixel fonts', function () + { + const style = PIXI.Text.getFontStyle({ fontSize: 72 }); + + expect(style).to.be.a.string; + expect(style).to.have.string(' 72px '); + }); + + it('should handle multiple fonts as array', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: ['Georgia', 'Arial', 'sans-serif'], + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + + it('should handle multiple fonts as string', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: 'Georgia, "Arial", sans-serif', + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + }); + describe('destroy', function () { it('should call through to Sprite.destroy', function () diff --git a/test/index.js b/test/index.js index 50a85da..9689aa0 100755 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ }); require('./core'); require('./interaction'); + require('./loaders'); require('./renders'); require('./prepare'); }); diff --git a/test/loaders/bitmapFontParser.js b/test/loaders/bitmapFontParser.js new file mode 100644 index 0000000..7c77343 --- /dev/null +++ b/test/loaders/bitmapFontParser.js @@ -0,0 +1,46 @@ +'use strict'; + +describe('PIXI.loaders.bitmapFontParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.bitmapFontParser).to.be.a('function'); + expect(PIXI.loaders.bitmapFontParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not XML', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should do nothing if the resource is not properly formatted XML', function () + { + const spy = sinon.spy(); + const res = { data: document.createDocumentFragment() }; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + // TODO: Test the texture cache code path. + // TODO: Test the loading texture code path. + // TODO: Test data-url code paths. +}); + +describe('PIXI.loaders.parseBitmapFontData', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.parseBitmapFontData).to.be.a('function'); + }); + + // TODO: Test the parser code. +}); diff --git a/test/loaders/index.js b/test/loaders/index.js new file mode 100644 index 0000000..97fc849 --- /dev/null +++ b/test/loaders/index.js @@ -0,0 +1,6 @@ +'use strict'; + +require('./bitmapFontParser'); +require('./loader'); +require('./spritesheetParser'); +require('./textureParser'); diff --git a/test/loaders/loader.js b/test/loaders/loader.js new file mode 100644 index 0000000..8ec6793 --- /dev/null +++ b/test/loaders/loader.js @@ -0,0 +1,9 @@ +'use strict'; + +describe('PIXI.loaders.Loader', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.Loader).to.be.a('function'); + }); +}); diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/test/core/Text.js b/test/core/Text.js index 4f67752..b8ce561 100644 --- a/test/core/Text.js +++ b/test/core/Text.js @@ -2,6 +2,40 @@ describe('PIXI.Text', function () { + describe('getFontStyle', function () + { + it('should be a valid API', function () + { + expect(PIXI.Text.getFontStyle).to.be.a.function; + }); + + it('should assume pixel fonts', function () + { + const style = PIXI.Text.getFontStyle({ fontSize: 72 }); + + expect(style).to.be.a.string; + expect(style).to.have.string(' 72px '); + }); + + it('should handle multiple fonts as array', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: ['Georgia', 'Arial', 'sans-serif'], + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + + it('should handle multiple fonts as string', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: 'Georgia, "Arial", sans-serif', + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + }); + describe('destroy', function () { it('should call through to Sprite.destroy', function () diff --git a/test/index.js b/test/index.js index 50a85da..9689aa0 100755 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ }); require('./core'); require('./interaction'); + require('./loaders'); require('./renders'); require('./prepare'); }); diff --git a/test/loaders/bitmapFontParser.js b/test/loaders/bitmapFontParser.js new file mode 100644 index 0000000..7c77343 --- /dev/null +++ b/test/loaders/bitmapFontParser.js @@ -0,0 +1,46 @@ +'use strict'; + +describe('PIXI.loaders.bitmapFontParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.bitmapFontParser).to.be.a('function'); + expect(PIXI.loaders.bitmapFontParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not XML', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should do nothing if the resource is not properly formatted XML', function () + { + const spy = sinon.spy(); + const res = { data: document.createDocumentFragment() }; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + // TODO: Test the texture cache code path. + // TODO: Test the loading texture code path. + // TODO: Test data-url code paths. +}); + +describe('PIXI.loaders.parseBitmapFontData', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.parseBitmapFontData).to.be.a('function'); + }); + + // TODO: Test the parser code. +}); diff --git a/test/loaders/index.js b/test/loaders/index.js new file mode 100644 index 0000000..97fc849 --- /dev/null +++ b/test/loaders/index.js @@ -0,0 +1,6 @@ +'use strict'; + +require('./bitmapFontParser'); +require('./loader'); +require('./spritesheetParser'); +require('./textureParser'); diff --git a/test/loaders/loader.js b/test/loaders/loader.js new file mode 100644 index 0000000..8ec6793 --- /dev/null +++ b/test/loaders/loader.js @@ -0,0 +1,9 @@ +'use strict'; + +describe('PIXI.loaders.Loader', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.Loader).to.be.a('function'); + }); +}); diff --git a/test/loaders/spritesheetParser.js b/test/loaders/spritesheetParser.js new file mode 100644 index 0000000..79f8c15 --- /dev/null +++ b/test/loaders/spritesheetParser.js @@ -0,0 +1,178 @@ +'use strict'; + +const path = require('path'); + +describe('PIXI.loaders.spritesheetParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.spritesheetParser).to.be.a('function'); + expect(PIXI.loaders.spritesheetParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not JSON', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.spritesheetParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should do nothing if the resource is JSON, but improper format', function () + { + const spy = sinon.spy(); + const res = createMockResource(PIXI.loaders.Resource.TYPE.JSON, {}); + + PIXI.loaders.spritesheetParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should load the image & create textures if json is properly formatted', function () + { + const spy = sinon.spy(); + const res = createMockResource(PIXI.loaders.Resource.TYPE.JSON, getJsonSpritesheet()); + const loader = new PIXI.loaders.Loader(); + const addStub = sinon.stub(loader, 'add'); + const imgRes = createMockResource(PIXI.loaders.Resource.TYPE.IMAGE, new Image()); + + imgRes.texture = new PIXI.Texture(new PIXI.BaseTexture(imgRes.data)); + + addStub.yields(imgRes); + + PIXI.loaders.spritesheetParser().call(loader, res, spy); + + addStub.restore(); + + expect(spy).to.have.been.calledOnce; + expect(addStub).to.have.been.calledWith( + `${res.name}_image`, + `${path.dirname(res.url)}/${res.data.meta.image}` + ); + expect(res).to.have.property('textures') + .that.is.an('object') + .with.keys(Object.keys(getJsonSpritesheet().frames)) + .and.has.property('0.png') + .that.is.an.instanceof(PIXI.Texture); + }); + + // TODO: Test that rectangles are created correctly. + // TODO: Test that bathc processing works correctly. + // TODO: Test that resolution processing works correctly. + // TODO: Test that metadata is honored. + // TODO: Test data-url code paths. +}); + +function createMockResource(type, data) +{ + const name = `${Math.floor(Date.now() * Math.random())}`; + + return { + url: `http://localhost/doesnt_exist/${name}`, + name, + type, + data, + metadata: {}, + }; +} + +function getJsonSpritesheet() +{ + /* eslint-disable */ + return {"frames": { + "0.png": + { + "frame": {"x":14,"y":28,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "1.png": + { + "frame": {"x":14,"y":42,"w":12,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":14}, + "sourceSize": {"w":12,"h":14} + }, + "2.png": + { + "frame": {"x":14,"y":14,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "3.png": + { + "frame": {"x":42,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "4.png": + { + "frame": {"x":28,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "5.png": + { + "frame": {"x":14,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "6.png": + { + "frame": {"x":0,"y":42,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "7.png": + { + "frame": {"x":0,"y":28,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "8.png": + { + "frame": {"x":0,"y":14,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "9.png": + { + "frame": {"x":0,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }}, + "meta": { + "app": "http://www.texturepacker.com", + "version": "1.0", + "image": "hud.png", + "format": "RGBA8888", + "size": {"w":64,"h":64}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:47025c98c8b10634b75172d4ed7e7edc$" + } + }; + /* eslint-enable */ +} diff --git a/.gitignore b/.gitignore index 1c378a5..914de54 100644 --- a/.gitignore +++ b/.gitignore @@ -22,12 +22,12 @@ !.gitkeep *__temp node_modules -docs/ -examples_old/ -bin/ -coverage/ -lib/ -dist/ +/docs +/examples_old +/bin +/coverage +/lib +/dist # jetBrains IDE ignores .idea \ No newline at end of file diff --git a/package.json b/package.json index 844f742..096ae2a 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "ismobilejs": "^0.4.0", "object-assign": "^4.0.1", "pixi-gl-core": "^1.0.3", - "resource-loader": "^1.8.0" + "resource-loader": "^2.0.3" }, "devDependencies": { "babel-cli": "^6.18.0", diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 53a3071..f552046 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -148,16 +148,6 @@ */ this.boundTextures = null; - this._initContext(); - /** - * Manages the filters. - * - * @member {PIXI.FilterManager} - */ - this.filterManager = new FilterManager(this); - // map some webGL blend and drawmodes.. - this.drawModes = mapWebGLDrawModesToPixi(this.gl); - /** * Holds the current shader * @@ -174,6 +164,17 @@ */ this._activeRenderTarget = null; + this._initContext(); + + /** + * Manages the filters. + * + * @member {PIXI.FilterManager} + */ + this.filterManager = new FilterManager(this); + // map some webGL blend and drawmodes.. + this.drawModes = mapWebGLDrawModesToPixi(this.gl); + this._nextTextureLocation = 0; this.setBlendMode(0); diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 0c48f61..4495081 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -44,7 +44,7 @@ this.vertByteSize = this.vertSize * 4; /** - * The number of images in the SpriteBatch before it flushes. + * The number of images in the SpriteRenderer before it flushes. * * @member {number} */ @@ -172,7 +172,7 @@ // get the uvs for the texture // if the uvs have not updated then no point rendering just yet! - if (!sprite.texture._uvs) + if (!sprite._texture._uvs) { return; } @@ -355,7 +355,7 @@ uint32View[index + 12] = uvs[2]; uint32View[index + 17] = uvs[3]; - uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (sprite.worldAlpha * 255 << 24); + uint32View[index + 3] = uint32View[index + 8] = uint32View[index + 13] = uint32View[index + 18] = sprite._tintRGB + (Math.min(sprite.worldAlpha, 1) * 255 << 24); float32View[index + 4] = float32View[index + 9] = float32View[index + 14] = float32View[index + 19] = nextTexture._virtalBoundId; @@ -367,7 +367,7 @@ if (!settings.CAN_UPLOAD_SAME_BUFFER) { // this is still needed for IOS performance.. - // it really does not like uploading to the same buffer in a single frame! + // it really does not like uploading to the same buffer in a single frame! if (this.vaoMax <= this.vertexCount) { this.vaoMax++; @@ -456,7 +456,7 @@ } /** - * Destroys the SpriteBatch. + * Destroys the SpriteRenderer. * */ destroy() diff --git a/src/core/text/Text.js b/src/core/text/Text.js index 4e94f6b..3aa3182 100644 --- a/src/core/text/Text.js +++ b/src/core/text/Text.js @@ -32,10 +32,11 @@ /** * @param {string} text - The string that you would like the text to display * @param {object|PIXI.TextStyle} [style] - The style parameters + * @param {HTMLCanvasElement} [canvas] - The canvas element for drawing text */ - constructor(text, style) + constructor(text, style, canvas) { - const canvas = document.createElement('canvas'); + canvas = canvas || document.createElement('canvas'); canvas.width = 3; canvas.height = 3; @@ -606,7 +607,7 @@ { this.updateText(true); - return Math.abs(this.scale.x) * this.texture.orig.width; + return Math.abs(this.scale.x) * this._texture.orig.width; } /** @@ -620,7 +621,7 @@ const s = sign(this.scale.x) || 1; - this.scale.x = s * value / this.texture.orig.width; + this.scale.x = s * value / this._texture.orig.width; this._width = value; } @@ -648,7 +649,7 @@ const s = sign(this.scale.y) || 1; - this.scale.y = s * value / this.texture.orig.height; + this.scale.y = s * value / this._texture.orig.height; this._height = value; } @@ -704,8 +705,7 @@ */ set text(text) { - text = text || ' '; - text = text.toString(); + text = String(text || ' '); if (this._text === text) { @@ -735,7 +735,29 @@ // build canvas api font setting from individual components. Convert a numeric style.fontSize to px const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize; - return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} "${style.fontFamily}"`; + // Clean-up fontFamily property by quoting each font name + // this will support font names with spaces + let fontFamilies = style.fontFamily; + + if (!Array.isArray(style.fontFamily)) + { + fontFamilies = style.fontFamily.split(','); + } + + for (let i = fontFamilies.length - 1; i >= 0; i--) + { + // Trim any extra white-space + let fontFamily = fontFamilies[i].trim(); + + // Check if font already contains strings + if (!(/([\"\'])[^\'\"]+\1/).test(fontFamily)) + { + fontFamily = `"${fontFamily}"`; + } + fontFamilies[i] = fontFamily; + } + + return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(',')}`; } /** diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index faeb91c..3b25528 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -57,7 +57,7 @@ * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} * @param {number} [style.fillGradientType=PIXI.TEXT_GRADIENT.LINEAR_VERTICAL] - If fills styles are * supplied, this can change the type/direction of the gradient. See {@link PIXI.TEXT_GRADIENT} for possible values - * @param {string} [style.fontFamily='Arial'] - The font family + * @param {string|string[]} [style.fontFamily='Arial'] - The font family * @param {number|string} [style.fontSize=26] - The font size (as a number it converts to px, but as a string, * equivalents are '26px','20pt','160%' or '1.6em') * @param {string} [style.fontStyle='normal'] - The font style ('normal', 'italic' or 'oblique') diff --git a/src/deprecation.js b/src/deprecation.js index e52d60b..045a19f 100644 --- a/src/deprecation.js +++ b/src/deprecation.js @@ -4,6 +4,7 @@ import * as extras from './extras'; import * as filters from './filters'; import * as prepare from './prepare'; +import * as loaders from './loaders'; // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -940,3 +941,65 @@ return NaN; }, }); + +Object.defineProperties(loaders.Resource.prototype, { + isJson: { + get() + { + warn('The isJson property is deprecated, please use `resource.type === Resource.TYPE.JSON`.'); + + return this.type === loaders.Loader.Resource.TYPE.JSON; + }, + }, + isXml: { + get() + { + warn('The isXml property is deprecated, please use `resource.type === Resource.TYPE.XML`.'); + + return this.type === loaders.Loader.Resource.TYPE.XML; + }, + }, + isImage: { + get() + { + warn('The isImage property is deprecated, please use `resource.type === Resource.TYPE.IMAGE`.'); + + return this.type === loaders.Loader.Resource.TYPE.IMAGE; + }, + }, + isAudio: { + get() + { + warn('The isAudio property is deprecated, please use `resource.type === Resource.TYPE.AUDIO`.'); + + return this.type === loaders.Loader.Resource.TYPE.AUDIO; + }, + }, + isVideo: { + get() + { + warn('The isVideo property is deprecated, please use `resource.type === Resource.TYPE.VIDEO`.'); + + return this.type === loaders.Loader.Resource.TYPE.VIDEO; + }, + }, +}); + +Object.defineProperties(loaders.Loader.prototype, { + before: { + get() + { + warn('The before() method is deprecated, please use pre().'); + + return this.pre; + }, + }, + after: { + get() + { + warn('The after() method is deprecated, please use use().'); + + return this.use; + }, + }, +}); diff --git a/src/extras/TextureTransform.js b/src/extras/TextureTransform.js index 88648b6..4f3db8a 100644 --- a/src/extras/TextureTransform.js +++ b/src/extras/TextureTransform.js @@ -4,6 +4,9 @@ /** * class controls uv transform and frame clamp for texture + * + * @class + * @memberof PIXI.extras */ export default class TextureTransform { /** @@ -27,7 +30,7 @@ /** * Changes frame clamping * Works with TilingSprite and Mesh - * Change to 1.5 if you tex ture has repeated right and bottom lines, that leads to smoother borders + * Change to 1.5 if you texture has repeated right and bottom lines, that leads to smoother borders * * @default 0 * @member {number} diff --git a/src/loaders/bitmapFontParser.js b/src/loaders/bitmapFontParser.js index 94a7cbc..cc2618c 100644 --- a/src/loaders/bitmapFontParser.js +++ b/src/loaders/bitmapFontParser.js @@ -65,7 +65,7 @@ return function bitmapFontParser(resource, next) { // skip if no data or not xml data - if (!resource.data || !resource.isXml) + if (!resource.data || resource.type !== Resource.TYPE.XML) { next(); @@ -125,6 +125,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // load the texture for the font diff --git a/src/loaders/loader.js b/src/loaders/loader.js index 978aa2d..0a670cb 100644 --- a/src/loaders/loader.js +++ b/src/loaders/loader.js @@ -1,4 +1,6 @@ import ResourceLoader from 'resource-loader'; +import { blobMiddlewareFactory } from 'resource-loader/lib/middlewares/parsing/blob'; +import EventEmitter from 'eventemitter3'; import textureParser from './textureParser'; import spritesheetParser from './spritesheetParser'; import bitmapFontParser from './bitmapFontParser'; @@ -36,11 +38,19 @@ constructor(baseUrl, concurrency) { super(baseUrl, concurrency); + EventEmitter.call(this); for (let i = 0; i < Loader._pixiMiddleware.length; ++i) { this.use(Loader._pixiMiddleware[i]()); } + + // Compat layer, translate the new v2 signals into old v1 events. + this.onStart.add((l) => this.emit('start', l)); + this.onProgress.add((l, r) => this.emit('progress', l, r)); + this.onError.add((e, l, r) => this.emit('error', e, l, r)); + this.onLoad.add((l, r) => this.emit('load', l, r)); + this.onComplete.add((l, r) => this.emit('complete', l, r)); } /** @@ -55,9 +65,15 @@ } } +// Copy EE3 prototype (mixin) +for (const k in EventEmitter.prototype) +{ + Loader.prototype[k] = EventEmitter.prototype[k]; +} + Loader._pixiMiddleware = [ // parse any blob into more usable objects (e.g. Image) - ResourceLoader.middleware.parsing.blob, + blobMiddlewareFactory, // parse any Image objects into textures textureParser, // parse any spritesheet data into multiple textures diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index 2b30b1c..7570332 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -12,7 +12,11 @@ const imageResourceName = `${resource.name}_image`; // skip if no data, its not json, it isn't spritesheet data, or the image resource already exists - if (!resource.data || !resource.isJson || !resource.data.frames || this.resources[imageResourceName]) + if (!resource.data + || resource.type !== Resource.TYPE.JSON + || !resource.data.frames + || this.resources[imageResourceName] + ) { next(); @@ -23,6 +27,7 @@ crossOrigin: resource.crossOrigin, loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, + parentResource: resource, }; // Prepend url path unless the resource image is a data url diff --git a/src/loaders/textureParser.js b/src/loaders/textureParser.js index 6bcbee6..5398a7f 100644 --- a/src/loaders/textureParser.js +++ b/src/loaders/textureParser.js @@ -1,11 +1,12 @@ import * as core from '../core'; +import { Resource } from 'resource-loader'; export default function () { return function textureParser(resource, next) { // create a new texture if the data is an Image object - if (resource.data && resource.isImage) + if (resource.data && resource.type === Resource.TYPE.IMAGE) { const baseTexture = new core.BaseTexture(resource.data, null, core.utils.getResolutionOfUrl(resource.url)); diff --git a/test/core/Text.js b/test/core/Text.js index 4f67752..b8ce561 100644 --- a/test/core/Text.js +++ b/test/core/Text.js @@ -2,6 +2,40 @@ describe('PIXI.Text', function () { + describe('getFontStyle', function () + { + it('should be a valid API', function () + { + expect(PIXI.Text.getFontStyle).to.be.a.function; + }); + + it('should assume pixel fonts', function () + { + const style = PIXI.Text.getFontStyle({ fontSize: 72 }); + + expect(style).to.be.a.string; + expect(style).to.have.string(' 72px '); + }); + + it('should handle multiple fonts as array', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: ['Georgia', 'Arial', 'sans-serif'], + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + + it('should handle multiple fonts as string', function () + { + const style = PIXI.Text.getFontStyle({ + fontFamily: 'Georgia, "Arial", sans-serif', + }); + + expect(style).to.have.string('"Georgia","Arial","sans-serif"'); + }); + }); + describe('destroy', function () { it('should call through to Sprite.destroy', function () diff --git a/test/index.js b/test/index.js index 50a85da..9689aa0 100755 --- a/test/index.js +++ b/test/index.js @@ -13,6 +13,7 @@ }); require('./core'); require('./interaction'); + require('./loaders'); require('./renders'); require('./prepare'); }); diff --git a/test/loaders/bitmapFontParser.js b/test/loaders/bitmapFontParser.js new file mode 100644 index 0000000..7c77343 --- /dev/null +++ b/test/loaders/bitmapFontParser.js @@ -0,0 +1,46 @@ +'use strict'; + +describe('PIXI.loaders.bitmapFontParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.bitmapFontParser).to.be.a('function'); + expect(PIXI.loaders.bitmapFontParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not XML', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should do nothing if the resource is not properly formatted XML', function () + { + const spy = sinon.spy(); + const res = { data: document.createDocumentFragment() }; + + PIXI.loaders.bitmapFontParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + // TODO: Test the texture cache code path. + // TODO: Test the loading texture code path. + // TODO: Test data-url code paths. +}); + +describe('PIXI.loaders.parseBitmapFontData', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.parseBitmapFontData).to.be.a('function'); + }); + + // TODO: Test the parser code. +}); diff --git a/test/loaders/index.js b/test/loaders/index.js new file mode 100644 index 0000000..97fc849 --- /dev/null +++ b/test/loaders/index.js @@ -0,0 +1,6 @@ +'use strict'; + +require('./bitmapFontParser'); +require('./loader'); +require('./spritesheetParser'); +require('./textureParser'); diff --git a/test/loaders/loader.js b/test/loaders/loader.js new file mode 100644 index 0000000..8ec6793 --- /dev/null +++ b/test/loaders/loader.js @@ -0,0 +1,9 @@ +'use strict'; + +describe('PIXI.loaders.Loader', function () +{ + it('should exist', function () + { + expect(PIXI.loaders.Loader).to.be.a('function'); + }); +}); diff --git a/test/loaders/spritesheetParser.js b/test/loaders/spritesheetParser.js new file mode 100644 index 0000000..79f8c15 --- /dev/null +++ b/test/loaders/spritesheetParser.js @@ -0,0 +1,178 @@ +'use strict'; + +const path = require('path'); + +describe('PIXI.loaders.spritesheetParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.spritesheetParser).to.be.a('function'); + expect(PIXI.loaders.spritesheetParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not JSON', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.spritesheetParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should do nothing if the resource is JSON, but improper format', function () + { + const spy = sinon.spy(); + const res = createMockResource(PIXI.loaders.Resource.TYPE.JSON, {}); + + PIXI.loaders.spritesheetParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.textures).to.be.undefined; + }); + + it('should load the image & create textures if json is properly formatted', function () + { + const spy = sinon.spy(); + const res = createMockResource(PIXI.loaders.Resource.TYPE.JSON, getJsonSpritesheet()); + const loader = new PIXI.loaders.Loader(); + const addStub = sinon.stub(loader, 'add'); + const imgRes = createMockResource(PIXI.loaders.Resource.TYPE.IMAGE, new Image()); + + imgRes.texture = new PIXI.Texture(new PIXI.BaseTexture(imgRes.data)); + + addStub.yields(imgRes); + + PIXI.loaders.spritesheetParser().call(loader, res, spy); + + addStub.restore(); + + expect(spy).to.have.been.calledOnce; + expect(addStub).to.have.been.calledWith( + `${res.name}_image`, + `${path.dirname(res.url)}/${res.data.meta.image}` + ); + expect(res).to.have.property('textures') + .that.is.an('object') + .with.keys(Object.keys(getJsonSpritesheet().frames)) + .and.has.property('0.png') + .that.is.an.instanceof(PIXI.Texture); + }); + + // TODO: Test that rectangles are created correctly. + // TODO: Test that bathc processing works correctly. + // TODO: Test that resolution processing works correctly. + // TODO: Test that metadata is honored. + // TODO: Test data-url code paths. +}); + +function createMockResource(type, data) +{ + const name = `${Math.floor(Date.now() * Math.random())}`; + + return { + url: `http://localhost/doesnt_exist/${name}`, + name, + type, + data, + metadata: {}, + }; +} + +function getJsonSpritesheet() +{ + /* eslint-disable */ + return {"frames": { + "0.png": + { + "frame": {"x":14,"y":28,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "1.png": + { + "frame": {"x":14,"y":42,"w":12,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":12,"h":14}, + "sourceSize": {"w":12,"h":14} + }, + "2.png": + { + "frame": {"x":14,"y":14,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "3.png": + { + "frame": {"x":42,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "4.png": + { + "frame": {"x":28,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "5.png": + { + "frame": {"x":14,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "6.png": + { + "frame": {"x":0,"y":42,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "7.png": + { + "frame": {"x":0,"y":28,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "8.png": + { + "frame": {"x":0,"y":14,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }, + "9.png": + { + "frame": {"x":0,"y":0,"w":14,"h":14}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, + "sourceSize": {"w":14,"h":14} + }}, + "meta": { + "app": "http://www.texturepacker.com", + "version": "1.0", + "image": "hud.png", + "format": "RGBA8888", + "size": {"w":64,"h":64}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:47025c98c8b10634b75172d4ed7e7edc$" + } + }; + /* eslint-enable */ +} diff --git a/test/loaders/textureParser.js b/test/loaders/textureParser.js new file mode 100644 index 0000000..e739e4d --- /dev/null +++ b/test/loaders/textureParser.js @@ -0,0 +1,50 @@ +'use strict'; + +describe('PIXI.loaders.textureParser', function () +{ + it('should exist and return a function', function () + { + expect(PIXI.loaders.textureParser).to.be.a('function'); + expect(PIXI.loaders.textureParser()).to.be.a('function'); + }); + + it('should do nothing if the resource is not an image', function () + { + const spy = sinon.spy(); + const res = {}; + + PIXI.loaders.textureParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.texture).to.be.undefined; + }); + + it('should create a texture if resource is an image', function () + { + const spy = sinon.spy(); + const res = createMockResource(PIXI.loaders.Resource.TYPE.IMAGE, new Image()); + + PIXI.loaders.textureParser()(res, spy); + + expect(spy).to.have.been.calledOnce; + expect(res.texture).to.be.an.instanceof(PIXI.Texture); + + expect(PIXI.utils.BaseTextureCache).to.have.property(res.name, res.texture.baseTexture); + expect(PIXI.utils.BaseTextureCache).to.have.property(res.url, res.texture.baseTexture); + + expect(PIXI.utils.TextureCache).to.have.property(res.name, res.texture); + expect(PIXI.utils.TextureCache).to.have.property(res.url, res.texture); + }); +}); + +function createMockResource(type, data) +{ + const name = `${Math.floor(Date.now() * Math.random())}`; + + return { + url: `http://localhost/doesnt_exist/${name}`, + name, + type, + data, + }; +}