diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/test/core/Graphics.js b/test/core/Graphics.js index 505df4c..0300129 100644 --- a/test/core/Graphics.js +++ b/test/core/Graphics.js @@ -1,6 +1,5 @@ 'use strict'; -const MockPointer = require('../interaction/MockPointer'); const withGL = require('../withGL'); describe('PIXI.Graphics', function () @@ -244,115 +243,8 @@ }); }); - describe('mask', function () + describe('fastRect', function () { - it('should trigger interaction callback when no mask present', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should calculate tint, alpha and blendMode of fastRect correctly', withGL(function () { const renderer = new PIXI.WebGLRenderer(200, 200, {}); diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/test/core/Graphics.js b/test/core/Graphics.js index 505df4c..0300129 100644 --- a/test/core/Graphics.js +++ b/test/core/Graphics.js @@ -1,6 +1,5 @@ 'use strict'; -const MockPointer = require('../interaction/MockPointer'); const withGL = require('../withGL'); describe('PIXI.Graphics', function () @@ -244,115 +243,8 @@ }); }); - describe('mask', function () + describe('fastRect', function () { - it('should trigger interaction callback when no mask present', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should calculate tint, alpha and blendMode of fastRect correctly', withGL(function () { const renderer = new PIXI.WebGLRenderer(200, 200, {}); diff --git a/test/core/Spritesheet.js b/test/core/Spritesheet.js index dccde04..2ee1136 100644 --- a/test/core/Spritesheet.js +++ b/test/core/Spritesheet.js @@ -27,6 +27,32 @@ done(); }); }; + + this.parseFrame = function (frameData, callback) + { + const data = { + frames: { frame: frameData }, + meta: { scale: 1 }, + }; + const baseTexture = PIXI.BaseTexture.fromCanvas( + document.createElement('canvas') + ); + + baseTexture.imageUrl = 'test.png'; + + const sheet = new PIXI.Spritesheet(baseTexture, data); + + sheet.parse(() => + { + const { frame } = sheet.textures; + + expect(frame).to.be.instanceof(PIXI.Texture); + + callback(frame); + + sheet.destroy(true); + }); + }; }); it('should exist on PIXI', function () @@ -102,4 +128,86 @@ this.validate(spritesheet, done); }; }); + + it('should parse full data untrimmed', function (done) + { + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 14, h: 16 }, + sourceSize: { w: 14, h: 16 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(16); + done(); + }); + }); + + it('should parse texture from trimmed', function (done) + { + const data = { + frame: { x: 0, y: 28, w: 14, h: 14 }, + rotated: false, + trimmed: true, + spriteSourceSize: { x: 0, y: 0, w: 40, h: 20 }, + sourceSize: { w: 40, h: 20 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(40); + expect(texture.height).to.equal(20); + done(); + }); + }); + + it('should parse texture from minimal data', function (done) + { + const data = { frame: { x: 0, y: 0, w: 14, h: 14 } }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse texture without trimmed or sourceSize', function (done) + { + const data = { + frame: { x: 0, y: 14, w: 14, h: 14 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 20, h: 30 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse as trimmed if spriteSourceSize is set', function (done) + { + // shoebox format + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + spriteSourceSize: { x: 0, y: 0, w: 120, h: 100 }, + sourceSize: { w: 120, h: 100 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(120); + expect(texture.height).to.equal(100); + done(); + }); + }); }); diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/test/core/Graphics.js b/test/core/Graphics.js index 505df4c..0300129 100644 --- a/test/core/Graphics.js +++ b/test/core/Graphics.js @@ -1,6 +1,5 @@ 'use strict'; -const MockPointer = require('../interaction/MockPointer'); const withGL = require('../withGL'); describe('PIXI.Graphics', function () @@ -244,115 +243,8 @@ }); }); - describe('mask', function () + describe('fastRect', function () { - it('should trigger interaction callback when no mask present', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should calculate tint, alpha and blendMode of fastRect correctly', withGL(function () { const renderer = new PIXI.WebGLRenderer(200, 200, {}); diff --git a/test/core/Spritesheet.js b/test/core/Spritesheet.js index dccde04..2ee1136 100644 --- a/test/core/Spritesheet.js +++ b/test/core/Spritesheet.js @@ -27,6 +27,32 @@ done(); }); }; + + this.parseFrame = function (frameData, callback) + { + const data = { + frames: { frame: frameData }, + meta: { scale: 1 }, + }; + const baseTexture = PIXI.BaseTexture.fromCanvas( + document.createElement('canvas') + ); + + baseTexture.imageUrl = 'test.png'; + + const sheet = new PIXI.Spritesheet(baseTexture, data); + + sheet.parse(() => + { + const { frame } = sheet.textures; + + expect(frame).to.be.instanceof(PIXI.Texture); + + callback(frame); + + sheet.destroy(true); + }); + }; }); it('should exist on PIXI', function () @@ -102,4 +128,86 @@ this.validate(spritesheet, done); }; }); + + it('should parse full data untrimmed', function (done) + { + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 14, h: 16 }, + sourceSize: { w: 14, h: 16 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(16); + done(); + }); + }); + + it('should parse texture from trimmed', function (done) + { + const data = { + frame: { x: 0, y: 28, w: 14, h: 14 }, + rotated: false, + trimmed: true, + spriteSourceSize: { x: 0, y: 0, w: 40, h: 20 }, + sourceSize: { w: 40, h: 20 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(40); + expect(texture.height).to.equal(20); + done(); + }); + }); + + it('should parse texture from minimal data', function (done) + { + const data = { frame: { x: 0, y: 0, w: 14, h: 14 } }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse texture without trimmed or sourceSize', function (done) + { + const data = { + frame: { x: 0, y: 14, w: 14, h: 14 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 20, h: 30 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse as trimmed if spriteSourceSize is set', function (done) + { + // shoebox format + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + spriteSourceSize: { x: 0, y: 0, w: 120, h: 100 }, + sourceSize: { w: 120, h: 100 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(120); + expect(texture.height).to.equal(100); + done(); + }); + }); }); diff --git a/test/interaction/InteractionManager.js b/test/interaction/InteractionManager.js index 136640e..4676252 100644 --- a/test/interaction/InteractionManager.js +++ b/test/interaction/InteractionManager.js @@ -1087,6 +1087,248 @@ }); }); + describe('masks', function () + { + it('should trigger interaction callback when no mask present', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask uses beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should not trigger interaction callback when mask doesn\'t use beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.not.been.called; + }); + + it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask is a sprite', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + }); + + describe('hitArea', function () + { + it('should trigger interaction callback when within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback when not within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + }); + describe('cursor changes', function () { it('cursor should be the cursor of interactive item', function () diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/test/core/Graphics.js b/test/core/Graphics.js index 505df4c..0300129 100644 --- a/test/core/Graphics.js +++ b/test/core/Graphics.js @@ -1,6 +1,5 @@ 'use strict'; -const MockPointer = require('../interaction/MockPointer'); const withGL = require('../withGL'); describe('PIXI.Graphics', function () @@ -244,115 +243,8 @@ }); }); - describe('mask', function () + describe('fastRect', function () { - it('should trigger interaction callback when no mask present', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should calculate tint, alpha and blendMode of fastRect correctly', withGL(function () { const renderer = new PIXI.WebGLRenderer(200, 200, {}); diff --git a/test/core/Spritesheet.js b/test/core/Spritesheet.js index dccde04..2ee1136 100644 --- a/test/core/Spritesheet.js +++ b/test/core/Spritesheet.js @@ -27,6 +27,32 @@ done(); }); }; + + this.parseFrame = function (frameData, callback) + { + const data = { + frames: { frame: frameData }, + meta: { scale: 1 }, + }; + const baseTexture = PIXI.BaseTexture.fromCanvas( + document.createElement('canvas') + ); + + baseTexture.imageUrl = 'test.png'; + + const sheet = new PIXI.Spritesheet(baseTexture, data); + + sheet.parse(() => + { + const { frame } = sheet.textures; + + expect(frame).to.be.instanceof(PIXI.Texture); + + callback(frame); + + sheet.destroy(true); + }); + }; }); it('should exist on PIXI', function () @@ -102,4 +128,86 @@ this.validate(spritesheet, done); }; }); + + it('should parse full data untrimmed', function (done) + { + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 14, h: 16 }, + sourceSize: { w: 14, h: 16 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(16); + done(); + }); + }); + + it('should parse texture from trimmed', function (done) + { + const data = { + frame: { x: 0, y: 28, w: 14, h: 14 }, + rotated: false, + trimmed: true, + spriteSourceSize: { x: 0, y: 0, w: 40, h: 20 }, + sourceSize: { w: 40, h: 20 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(40); + expect(texture.height).to.equal(20); + done(); + }); + }); + + it('should parse texture from minimal data', function (done) + { + const data = { frame: { x: 0, y: 0, w: 14, h: 14 } }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse texture without trimmed or sourceSize', function (done) + { + const data = { + frame: { x: 0, y: 14, w: 14, h: 14 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 20, h: 30 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse as trimmed if spriteSourceSize is set', function (done) + { + // shoebox format + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + spriteSourceSize: { x: 0, y: 0, w: 120, h: 100 }, + sourceSize: { w: 120, h: 100 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(120); + expect(texture.height).to.equal(100); + done(); + }); + }); }); diff --git a/test/interaction/InteractionManager.js b/test/interaction/InteractionManager.js index 136640e..4676252 100644 --- a/test/interaction/InteractionManager.js +++ b/test/interaction/InteractionManager.js @@ -1087,6 +1087,248 @@ }); }); + describe('masks', function () + { + it('should trigger interaction callback when no mask present', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask uses beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should not trigger interaction callback when mask doesn\'t use beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.not.been.called; + }); + + it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask is a sprite', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + }); + + describe('hitArea', function () + { + it('should trigger interaction callback when within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback when not within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + }); + describe('cursor changes', function () { it('cursor should be the cursor of interactive item', function () diff --git a/test/loaders/resources/atlas.crn b/test/loaders/resources/atlas.crn new file mode 100644 index 0000000..d5e7892 --- /dev/null +++ b/test/loaders/resources/atlas.crn Binary files differ diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/test/core/Graphics.js b/test/core/Graphics.js index 505df4c..0300129 100644 --- a/test/core/Graphics.js +++ b/test/core/Graphics.js @@ -1,6 +1,5 @@ 'use strict'; -const MockPointer = require('../interaction/MockPointer'); const withGL = require('../withGL'); describe('PIXI.Graphics', function () @@ -244,115 +243,8 @@ }); }); - describe('mask', function () + describe('fastRect', function () { - it('should trigger interaction callback when no mask present', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should calculate tint, alpha and blendMode of fastRect correctly', withGL(function () { const renderer = new PIXI.WebGLRenderer(200, 200, {}); diff --git a/test/core/Spritesheet.js b/test/core/Spritesheet.js index dccde04..2ee1136 100644 --- a/test/core/Spritesheet.js +++ b/test/core/Spritesheet.js @@ -27,6 +27,32 @@ done(); }); }; + + this.parseFrame = function (frameData, callback) + { + const data = { + frames: { frame: frameData }, + meta: { scale: 1 }, + }; + const baseTexture = PIXI.BaseTexture.fromCanvas( + document.createElement('canvas') + ); + + baseTexture.imageUrl = 'test.png'; + + const sheet = new PIXI.Spritesheet(baseTexture, data); + + sheet.parse(() => + { + const { frame } = sheet.textures; + + expect(frame).to.be.instanceof(PIXI.Texture); + + callback(frame); + + sheet.destroy(true); + }); + }; }); it('should exist on PIXI', function () @@ -102,4 +128,86 @@ this.validate(spritesheet, done); }; }); + + it('should parse full data untrimmed', function (done) + { + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 14, h: 16 }, + sourceSize: { w: 14, h: 16 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(16); + done(); + }); + }); + + it('should parse texture from trimmed', function (done) + { + const data = { + frame: { x: 0, y: 28, w: 14, h: 14 }, + rotated: false, + trimmed: true, + spriteSourceSize: { x: 0, y: 0, w: 40, h: 20 }, + sourceSize: { w: 40, h: 20 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(40); + expect(texture.height).to.equal(20); + done(); + }); + }); + + it('should parse texture from minimal data', function (done) + { + const data = { frame: { x: 0, y: 0, w: 14, h: 14 } }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse texture without trimmed or sourceSize', function (done) + { + const data = { + frame: { x: 0, y: 14, w: 14, h: 14 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 20, h: 30 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse as trimmed if spriteSourceSize is set', function (done) + { + // shoebox format + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + spriteSourceSize: { x: 0, y: 0, w: 120, h: 100 }, + sourceSize: { w: 120, h: 100 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(120); + expect(texture.height).to.equal(100); + done(); + }); + }); }); diff --git a/test/interaction/InteractionManager.js b/test/interaction/InteractionManager.js index 136640e..4676252 100644 --- a/test/interaction/InteractionManager.js +++ b/test/interaction/InteractionManager.js @@ -1087,6 +1087,248 @@ }); }); + describe('masks', function () + { + it('should trigger interaction callback when no mask present', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask uses beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should not trigger interaction callback when mask doesn\'t use beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.not.been.called; + }); + + it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask is a sprite', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + }); + + describe('hitArea', function () + { + it('should trigger interaction callback when within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback when not within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + }); + describe('cursor changes', function () { it('cursor should be the cursor of interactive item', function () diff --git a/test/loaders/resources/atlas.crn b/test/loaders/resources/atlas.crn new file mode 100644 index 0000000..d5e7892 --- /dev/null +++ b/test/loaders/resources/atlas.crn Binary files differ diff --git a/test/loaders/resources/atlas_crn.json b/test/loaders/resources/atlas_crn.json new file mode 100644 index 0000000..6327c0b --- /dev/null +++ b/test/loaders/resources/atlas_crn.json @@ -0,0 +1,25 @@ +{ + "meta": { + "image": "atlas.crn", + "size": {"w":256,"h":256}, + "scale": "1" + }, + "frames": { + "resources/test.png": + { + "frame": {"x":2,"y":2,"w":152,"h":188}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":74,"y":36,"w":152,"h":188}, + "sourceSize": {"w":300,"h":225} + }, + "resources/font.png": + { + "frame": {"x":158,"y":2,"w":40,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":40,"h":42}, + "sourceSize": {"w":43,"h":46} + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/test/core/Graphics.js b/test/core/Graphics.js index 505df4c..0300129 100644 --- a/test/core/Graphics.js +++ b/test/core/Graphics.js @@ -1,6 +1,5 @@ 'use strict'; -const MockPointer = require('../interaction/MockPointer'); const withGL = require('../withGL'); describe('PIXI.Graphics', function () @@ -244,115 +243,8 @@ }); }); - describe('mask', function () + describe('fastRect', function () { - it('should trigger interaction callback when no mask present', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should calculate tint, alpha and blendMode of fastRect correctly', withGL(function () { const renderer = new PIXI.WebGLRenderer(200, 200, {}); diff --git a/test/core/Spritesheet.js b/test/core/Spritesheet.js index dccde04..2ee1136 100644 --- a/test/core/Spritesheet.js +++ b/test/core/Spritesheet.js @@ -27,6 +27,32 @@ done(); }); }; + + this.parseFrame = function (frameData, callback) + { + const data = { + frames: { frame: frameData }, + meta: { scale: 1 }, + }; + const baseTexture = PIXI.BaseTexture.fromCanvas( + document.createElement('canvas') + ); + + baseTexture.imageUrl = 'test.png'; + + const sheet = new PIXI.Spritesheet(baseTexture, data); + + sheet.parse(() => + { + const { frame } = sheet.textures; + + expect(frame).to.be.instanceof(PIXI.Texture); + + callback(frame); + + sheet.destroy(true); + }); + }; }); it('should exist on PIXI', function () @@ -102,4 +128,86 @@ this.validate(spritesheet, done); }; }); + + it('should parse full data untrimmed', function (done) + { + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 14, h: 16 }, + sourceSize: { w: 14, h: 16 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(16); + done(); + }); + }); + + it('should parse texture from trimmed', function (done) + { + const data = { + frame: { x: 0, y: 28, w: 14, h: 14 }, + rotated: false, + trimmed: true, + spriteSourceSize: { x: 0, y: 0, w: 40, h: 20 }, + sourceSize: { w: 40, h: 20 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(40); + expect(texture.height).to.equal(20); + done(); + }); + }); + + it('should parse texture from minimal data', function (done) + { + const data = { frame: { x: 0, y: 0, w: 14, h: 14 } }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse texture without trimmed or sourceSize', function (done) + { + const data = { + frame: { x: 0, y: 14, w: 14, h: 14 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 20, h: 30 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse as trimmed if spriteSourceSize is set', function (done) + { + // shoebox format + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + spriteSourceSize: { x: 0, y: 0, w: 120, h: 100 }, + sourceSize: { w: 120, h: 100 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(120); + expect(texture.height).to.equal(100); + done(); + }); + }); }); diff --git a/test/interaction/InteractionManager.js b/test/interaction/InteractionManager.js index 136640e..4676252 100644 --- a/test/interaction/InteractionManager.js +++ b/test/interaction/InteractionManager.js @@ -1087,6 +1087,248 @@ }); }); + describe('masks', function () + { + it('should trigger interaction callback when no mask present', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask uses beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should not trigger interaction callback when mask doesn\'t use beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.not.been.called; + }); + + it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask is a sprite', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + }); + + describe('hitArea', function () + { + it('should trigger interaction callback when within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback when not within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + }); + describe('cursor changes', function () { it('cursor should be the cursor of interactive item', function () diff --git a/test/loaders/resources/atlas.crn b/test/loaders/resources/atlas.crn new file mode 100644 index 0000000..d5e7892 --- /dev/null +++ b/test/loaders/resources/atlas.crn Binary files differ diff --git a/test/loaders/resources/atlas_crn.json b/test/loaders/resources/atlas_crn.json new file mode 100644 index 0000000..6327c0b --- /dev/null +++ b/test/loaders/resources/atlas_crn.json @@ -0,0 +1,25 @@ +{ + "meta": { + "image": "atlas.crn", + "size": {"w":256,"h":256}, + "scale": "1" + }, + "frames": { + "resources/test.png": + { + "frame": {"x":2,"y":2,"w":152,"h":188}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":74,"y":36,"w":152,"h":188}, + "sourceSize": {"w":300,"h":225} + }, + "resources/font.png": + { + "frame": {"x":158,"y":2,"w":40,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":40,"h":42}, + "sourceSize": {"w":43,"h":46} + } + } +} \ No newline at end of file diff --git a/test/loaders/resources/atlas_error.json b/test/loaders/resources/atlas_error.json new file mode 100644 index 0000000..531a124 --- /dev/null +++ b/test/loaders/resources/atlas_error.json @@ -0,0 +1,17 @@ +{ + "frames": { + "boss1.png": { + "frame": {"x":1,"y":1,"w":168,"h":168}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":168,"h":168}, + "sourceSize": {"w":168,"h":168} + } + }, + "meta": { + "image": "invalid.png", + "format": "RGBA8888", + "size": {"w":170,"h":170}, + "scale": "1" + } +} \ No newline at end of file diff --git a/README.md b/README.md index 427f3d7..97358f9 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PixiJS — The HTML5 Creation Engine ============= -![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) +![pixi.js logo](http://pixijs.download/pixijs-banner.png) [![Inline docs](http://inch-ci.org/github/pixijs/pixi.js.svg?branch=dev)](http://inch-ci.org/github/pixijs/pixi.js) [![Build Status](https://travis-ci.org/pixijs/pixi.js.svg?branch=dev)](https://travis-ci.org/pixijs/pixi.js) @@ -62,13 +62,12 @@ ### Demos ### -- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) -- [Run pixie run](http://www.goodboydigital.com/runpixierun) +- [Filters Demo](http://pixijs.io/pixi-filters/tools/demo/) +- [Run Pixie Run](http://work.goodboydigital.com/runpixierun/) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) - [Bunny Demo](http://www.goodboydigital.com/pixijs/bunnymark) - [Storm Brewing](http://www.goodboydigital.com/pixijs/storm) -- [Filters Demo](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) - [Render Texture Demo](http://www.goodboydigital.com/pixijs/examples/11) - [Primitives Demo](http://www.goodboydigital.com/pixijs/examples/13) - [Masking Demo](http://www.goodboydigital.com/pixijs/examples/14) diff --git a/package.json b/package.json index 6320e1a..5a2245b 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "object-assign": "^4.0.1", "pixi-gl-core": "^1.1.4", "remove-array-items": "^1.0.0", - "resource-loader": "^2.0.9" + "resource-loader": "^2.1.1" }, "devDependencies": { "@pixi/jsdoc-template": "^2.0.0", diff --git a/src/core/Shader.js b/src/core/Shader.js index 78b17e6..d83ddda 100644 --- a/src/core/Shader.js +++ b/src/core/Shader.js @@ -14,7 +14,7 @@ return copy; } } - else if (src.substring(0, 9) !== 'precision') + else if (src.trim().substring(0, 9) !== 'precision') { return `precision ${def} float;\n${src}`; } @@ -37,10 +37,13 @@ * @param {WebGLRenderingContext} gl - The current WebGL rendering context * @param {string|string[]} vertexSrc - The vertex shader source as an array of strings. * @param {string|string[]} fragmentSrc - The fragment shader source as an array of strings. + * @param {object} [attributeLocations] - A key value pair showing which location eact attribute should sit. + e.g. {position:0, uvs:1}. + * @param {string} [precision] - The float precision of the shader. Options are 'lowp', 'mediump' or 'highp'. */ - constructor(gl, vertexSrc, fragmentSrc) + constructor(gl, vertexSrc, fragmentSrc, attributeLocations, precision) { - super(gl, checkPrecision(vertexSrc, settings.PRECISION_VERTEX), - checkPrecision(fragmentSrc, settings.PRECISION_FRAGMENT)); + super(gl, checkPrecision(vertexSrc, precision || settings.PRECISION_VERTEX), + checkPrecision(fragmentSrc, precision || settings.PRECISION_FRAGMENT), undefined, attributeLocations); } } diff --git a/src/core/display/DisplayObject.js b/src/core/display/DisplayObject.js index decb42a..c306d05 100644 --- a/src/core/display/DisplayObject.js +++ b/src/core/display/DisplayObject.js @@ -605,6 +605,7 @@ if (this._mask) { this._mask.renderable = true; + this._mask.isMask = false; } this._mask = value; @@ -612,6 +613,7 @@ if (this._mask) { this._mask.renderable = false; + this._mask.isMask = true; } } diff --git a/src/core/graphics/Graphics.js b/src/core/graphics/Graphics.js index 5b56f09..8083d2a 100644 --- a/src/core/graphics/Graphics.js +++ b/src/core/graphics/Graphics.js @@ -5,7 +5,7 @@ import Sprite from '../sprites/Sprite'; import { Matrix, Point, Rectangle, RoundedRectangle, Ellipse, Polygon, Circle } from '../math'; import { hex2rgb, rgb2hex } from '../utils'; -import { SHAPES, BLEND_MODES } from '../const'; +import { SHAPES, BLEND_MODES, PI_2 } from '../const'; import Bounds from '../display/Bounds'; import bezierCurveTo from './utils/bezierCurveTo'; import CanvasRenderer from '../renderers/canvas/CanvasRenderer'; @@ -481,15 +481,15 @@ if (!anticlockwise && endAngle <= startAngle) { - endAngle += Math.PI * 2; + endAngle += PI_2; } else if (anticlockwise && startAngle <= endAngle) { - startAngle += Math.PI * 2; + startAngle += PI_2; } const sweep = endAngle - startAngle; - const segs = Math.ceil(Math.abs(sweep) / (Math.PI * 2)) * 40; + const segs = Math.ceil(Math.abs(sweep) / PI_2) * 40; if (sweep === 0) { @@ -690,6 +690,40 @@ } /** + * Draw a star shape with an abitrary number of points. + * + * @param {number} x - Center X position of the star + * @param {number} y - Center Y position of the star + * @param {number} points - The number of points of the star, must be > 1 + * @param {number} radius - The outer radius of the star + * @param {number} [innerRadius] - The inner radius between points, default half `radius` + * @param {number} [rotation=0] - The rotation of the star in radians, where 0 is vertical + * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls + */ + drawStar(x, y, points, radius, innerRadius, rotation = 0) + { + innerRadius = innerRadius || radius / 2; + + const startAngle = (-1 * Math.PI / 2) + rotation; + const len = points * 2; + const delta = PI_2 / len; + const polygon = []; + + for (let i = 0; i < len; i++) + { + const r = i % 2 ? innerRadius : radius; + const angle = (i * delta) + startAngle; + + polygon.push( + x + (r * Math.cos(angle)), + y + (r * Math.sin(angle)) + ); + } + + return this.drawPolygon(polygon); + } + + /** * Clears the graphics that were drawn to this Graphics object, and resets fill and line style settings. * * @return {PIXI.Graphics} This Graphics object. Good for chaining method calls diff --git a/src/core/graphics/GraphicsData.js b/src/core/graphics/GraphicsData.js index b6f03c0..f9ff7ed 100644 --- a/src/core/graphics/GraphicsData.js +++ b/src/core/graphics/GraphicsData.js @@ -20,58 +20,72 @@ constructor(lineWidth, lineColor, lineAlpha, fillColor, fillAlpha, fill, nativeLines, shape) { /** - * @member {number} the width of the line to draw + * the width of the line to draw + * @member {number} */ this.lineWidth = lineWidth; + /** - * @member {boolean} if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * if true the liens will be draw using LINES instead of TRIANGLE_STRIP + * @member {boolean} */ this.nativeLines = nativeLines; /** - * @member {number} the color of the line to draw + * the color of the line to draw + * @member {number} */ this.lineColor = lineColor; /** - * @member {number} the alpha of the line to draw + * the alpha of the line to draw + * @member {number} */ this.lineAlpha = lineAlpha; /** - * @member {number} cached tint of the line to draw + * cached tint of the line to draw + * @member {number} + * @private */ this._lineTint = lineColor; /** - * @member {number} the color of the fill + * the color of the fill + * @member {number} */ this.fillColor = fillColor; /** - * @member {number} the alpha of the fill + * the alpha of the fill + * @member {number} */ this.fillAlpha = fillAlpha; /** - * @member {number} cached tint of the fill + * cached tint of the fill + * @member {number} + * @private */ this._fillTint = fillColor; /** - * @member {boolean} whether or not the shape is filled with a colour + * whether or not the shape is filled with a colour + * @member {boolean} */ this.fill = fill; this.holes = []; /** - * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} The shape object to draw. + * The shape object to draw. + * @member {PIXI.Circle|PIXI.Ellipse|PIXI.Polygon|PIXI.Rectangle|PIXI.RoundedRectangle} */ this.shape = shape; /** - * @member {number} The type of the shape, see the Const.Shapes file for all the existing types, + * The type of the shape, see the Const.Shapes file for all the existing types, + * @member {number} */ this.type = shape.type; } diff --git a/src/core/renderers/webgl/filters/filterTransforms.js b/src/core/renderers/webgl/filters/filterTransforms.js index 2d08dbc..706e422 100644 --- a/src/core/renderers/webgl/filters/filterTransforms.js +++ b/src/core/renderers/webgl/filters/filterTransforms.js @@ -5,6 +5,7 @@ * @param filterArea {Rectangle} The filter area * @param sprite {Sprite} the target sprite * @param outputMatrix {Matrix} @alvin + * @private */ // TODO playing around here.. this is temporary - (will end up in the shader) // this returns a matrix that will normalise map filter cords in the filter to screen space diff --git a/src/core/settings.js b/src/core/settings.js index d75b058..9fa4f8f 100644 --- a/src/core/settings.js +++ b/src/core/settings.js @@ -214,9 +214,19 @@ * * @static * @constant - * @memberof PIXI + * @memberof PIXI.settings * @type {boolean} */ CAN_UPLOAD_SAME_BUFFER: canUploadSameBuffer(), + /** + * Default Mesh `canvasPadding`. + * + * @see PIXI.mesh.Mesh#canvasPadding + * @static + * @constant + * @memberof PIXI.settings + * @type {number} + */ + MESH_CANVAS_PADDING: 0, }; diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index c7ab5c2..6b1b00d 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -680,7 +680,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -704,7 +704,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {number|number[]} color * @return {string} The color as a string. */ @@ -728,7 +728,7 @@ /** * Utility function to convert hexadecimal colors to strings, and simply return the color if it's a string. * This version can also convert array of colors - * + * @private * @param {Array} array1 First array to compare * @param {Array} array2 Second array to compare * @return {boolean} Do the arrays contain the same values in the same order @@ -758,7 +758,7 @@ /** * Utility function to ensure that object properties are copied by value, and not by reference - * + * @private * @param {Object} target Target object to copy properties into * @param {Object} source Source object for the proporties to copy * @param {string} propertyObj Object containing properties names we want to loop over diff --git a/src/core/textures/Spritesheet.js b/src/core/textures/Spritesheet.js index 1a9223f..adb555c 100644 --- a/src/core/textures/Spritesheet.js +++ b/src/core/textures/Spritesheet.js @@ -156,20 +156,24 @@ while (frameIndex - initialFrameIndex < maxFrames && frameIndex < this._frameKeys.length) { const i = this._frameKeys[frameIndex]; - const rect = this._frames[i].frame; + const data = this._frames[i]; + const rect = data.frame; if (rect) { let frame = null; let trim = null; + const sourceSize = data.trimmed !== false && data.sourceSize + ? data.sourceSize : data.frame; + const orig = new Rectangle( 0, 0, - Math.floor(this._frames[i].sourceSize.w * sourceScale) / this.resolution, - Math.floor(this._frames[i].sourceSize.h * sourceScale) / this.resolution + Math.floor(sourceSize.w * sourceScale) / this.resolution, + Math.floor(sourceSize.h * sourceScale) / this.resolution ); - if (this._frames[i].rotated) + if (data.rotated) { frame = new Rectangle( Math.floor(rect.x * sourceScale) / this.resolution, @@ -189,11 +193,11 @@ } // Check to see if the sprite is trimmed - if (this._frames[i].trimmed) + if (data.trimmed !== false && data.spriteSourceSize) { trim = new Rectangle( - Math.floor(this._frames[i].spriteSourceSize.x * sourceScale) / this.resolution, - Math.floor(this._frames[i].spriteSourceSize.y * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.x * sourceScale) / this.resolution, + Math.floor(data.spriteSourceSize.y * sourceScale) / this.resolution, Math.floor(rect.w * sourceScale) / this.resolution, Math.floor(rect.h * sourceScale) / this.resolution ); @@ -204,7 +208,7 @@ frame, orig, trim, - this._frames[i].rotated ? 2 : 0 + data.rotated ? 2 : 0 ); // lets also add the frame to pixi's global cache for fromFrame and fromImage functions diff --git a/src/core/utils/index.js b/src/core/utils/index.js index 18dbaa2..a0f560d 100644 --- a/src/core/utils/index.js +++ b/src/core/utils/index.js @@ -149,7 +149,7 @@ /** * Typedef for decomposeDataUri return object. * - * @typedef {object} DecomposedDataUri + * @typedef {object} PIXI.utils~DecomposedDataUri * @property {mediaType} Media type, eg. `image` * @property {subType} Sub type, eg. `png` * @property {encoding} Data encoding, eg. `base64` @@ -163,7 +163,7 @@ * @memberof PIXI.utils * @function decomposeDataUri * @param {string} dataUri - the data URI to check - * @return {DecomposedDataUri|undefined} The decomposed data uri or undefined + * @return {PIXI.utils~DecomposedDataUri|undefined} The decomposed data uri or undefined */ export function decomposeDataUri(dataUri) { @@ -205,7 +205,7 @@ /** * Typedef for Size object. * - * @typedef {object} Size + * @typedef {object} PIXI.utils~Size * @property {width} Width component * @property {height} Height component */ @@ -216,7 +216,7 @@ * @memberof PIXI.utils * @function getSvgSize * @param {string} svgString - a serialized svg element - * @return {Size|undefined} image extension + * @return {PIXI.utils~Size|undefined} image extension */ export function getSvgSize(svgString) { @@ -424,6 +424,7 @@ /** * premultiplies tint * + * @memberof PIXI.utils * @param {number} tint integet RGB * @param {number} alpha floating point alpha (0.0-1.0) * @returns {number} tint multiplied by alpha @@ -452,6 +453,7 @@ /** * combines rgb and alpha to out array * + * @memberof PIXI.utils * @param {Float32Array|number[]} rgb input rgb * @param {number} alpha alpha param * @param {Float32Array} [out] output @@ -481,6 +483,7 @@ /** * converts integer tint and float alpha to vec4 form, premultiplies by default * + * @memberof PIXI.utils * @param {number} tint input tint * @param {number} alpha alpha param * @param {Float32Array} [out] output diff --git a/src/extract/webgl/WebGLExtract.js b/src/extract/webgl/WebGLExtract.js index 1c3dd30..7bb3ee6 100644 --- a/src/extract/webgl/WebGLExtract.js +++ b/src/extract/webgl/WebGLExtract.js @@ -73,6 +73,7 @@ let frame; let flipY = false; let renderTexture; + let generated = false; if (target) { @@ -83,6 +84,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -145,7 +147,12 @@ } } - // send the canvas back.. + if (generated) + { + renderTexture.destroy(true); + } + // send the canvas back.. + return canvasBuffer.canvas; } @@ -164,6 +171,7 @@ let resolution; let frame; let renderTexture; + let generated = false; if (target) { @@ -174,6 +182,7 @@ else { renderTexture = this.renderer.generateTexture(target); + generated = true; } } @@ -216,6 +225,11 @@ ); } + if (generated) + { + renderTexture.destroy(true); + } + return webglPixels; } diff --git a/src/extras/AnimatedSprite.js b/src/extras/AnimatedSprite.js index c605fa8..e538dd4 100644 --- a/src/extras/AnimatedSprite.js +++ b/src/extras/AnimatedSprite.js @@ -1,7 +1,7 @@ import * as core from '../core'; /** - * @typedef FrameObject + * @typedef PIXI.extras.AnimatedSprite~FrameObject * @type {object} * @property {PIXI.Texture} texture - The {@link PIXI.Texture} of the frame * @property {number} time - the duration of the frame in ms @@ -30,7 +30,7 @@ export default class AnimatedSprite extends core.Sprite { /** - * @param {PIXI.Texture[]|FrameObject[]} textures - an array of {@link PIXI.Texture} or frame + * @param {PIXI.Texture[]|PIXI.extras.AnimatedSprite~FrameObject[]} textures - an array of {@link PIXI.Texture} or frame * objects that make up the animation * @param {boolean} [autoUpdate=true] - Whether to use PIXI.ticker.shared to auto update animation time. */ diff --git a/src/extras/getChildByName.js b/src/extras/getChildByName.js index f8ff40c..24ab420 100644 --- a/src/extras/getChildByName.js +++ b/src/extras/getChildByName.js @@ -4,13 +4,14 @@ * The instance name of the object. * * @memberof PIXI.DisplayObject# - * @member {string} + * @member {string} name */ core.DisplayObject.prototype.name = null; /** * Returns the display object in the container * + * @method getChildByName * @memberof PIXI.Container# * @param {string} name - instance name * @return {PIXI.DisplayObject} The child with the specified name. diff --git a/src/extras/getGlobalPosition.js b/src/extras/getGlobalPosition.js index a23761f..3065a29 100644 --- a/src/extras/getGlobalPosition.js +++ b/src/extras/getGlobalPosition.js @@ -3,6 +3,7 @@ /** * Returns the global position of the displayObject. Does not depend on object scale, rotation and pivot. * + * @method getGlobalPosition * @memberof PIXI.DisplayObject# * @param {Point} point - the point to write the global value to. If null a new point will be returned * @param {boolean} skipUpdate - setting to true will stop the transforms of the scene graph from diff --git a/src/filters/displacement/DisplacementFilter.js b/src/filters/displacement/DisplacementFilter.js index b5d030c..a50bdc6 100644 --- a/src/filters/displacement/DisplacementFilter.js +++ b/src/filters/displacement/DisplacementFilter.js @@ -56,11 +56,9 @@ */ apply(filterManager, input, output) { - const ratio = (1 / output.destinationFrame.width) * (output.size.width / input.size.width); - this.uniforms.filterMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = this.scale.x; + this.uniforms.scale.y = this.scale.y; // draw the filter... filterManager.applyFilter(this, input, output); diff --git a/src/filters/displacement/displacement.frag b/src/filters/displacement/displacement.frag index e7e4053..c310299 100644 --- a/src/filters/displacement/displacement.frag +++ b/src/filters/displacement/displacement.frag @@ -6,14 +6,15 @@ uniform sampler2D uSampler; uniform sampler2D mapSampler; +uniform vec4 filterArea; uniform vec4 filterClamp; void main(void) { - vec4 map = texture2D(mapSampler, vFilterCoord); + vec4 map = texture2D(mapSampler, vFilterCoord); - map -= 0.5; - map.xy *= scale; + map -= 0.5; + map.xy *= scale / filterArea.xy; - gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); + gl_FragColor = texture2D(uSampler, clamp(vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y), filterClamp.xy, filterClamp.zw)); } diff --git a/src/interaction/InteractionManager.js b/src/interaction/InteractionManager.js index 32dc791..b1a9c41 100644 --- a/src/interaction/InteractionManager.js +++ b/src/interaction/InteractionManager.js @@ -11,7 +11,7 @@ interactiveTarget ); -const MOUSE_POINTER_ID = 'MOUSE'; +const MOUSE_POINTER_ID = 1; // helpers for hitTest() - only used inside hitTest() const hitTestEvent = { @@ -1014,24 +1014,45 @@ let hit = false; let interactiveParent = interactive; - // if the displayobject has a hitArea, then it does not need to hitTest children. + // Flag here can set to false if the event is outside the parents hitArea or mask + let hitTestChildren = true; + + // If there is a hitArea, no need to test against anything else if the pointer is not within the hitArea + // There is also no longer a need to hitTest children. if (displayObject.hitArea) { + if (hitTest) + { + displayObject.worldTransform.applyInverse(point, this._tempPoint); + if (!displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) + { + hitTest = false; + hitTestChildren = false; + } + else + { + hit = true; + } + } interactiveParent = false; } - // it has a mask! Then lets hit test that before continuing - else if (hitTest && displayObject._mask) + // If there is a mask, no need to test against anything else if the pointer is not within the mask + else if (displayObject._mask) { - if (!displayObject._mask.containsPoint(point)) + if (hitTest) { - hitTest = false; + if (!displayObject._mask.containsPoint(point)) + { + hitTest = false; + hitTestChildren = false; + } } } // ** FREE TIP **! If an object is not interactive or has no buttons in it // (such as a game scene!) set interactiveChildren to false for that displayObject. // This will allow PixiJS to completely ignore and bypass checking the displayObjects children. - if (displayObject.interactiveChildren && displayObject.children) + if (hitTestChildren && displayObject.interactiveChildren && displayObject.children) { const children = displayObject.children; @@ -1081,15 +1102,8 @@ // looking for an interactive child, just in case we hit one if (hitTest && !interactionEvent.target) { - if (displayObject.hitArea) - { - displayObject.worldTransform.applyInverse(point, this._tempPoint); - if (displayObject.hitArea.contains(this._tempPoint.x, this._tempPoint.y)) - { - hit = true; - } - } - else if (displayObject.containsPoint) + // already tested against hitArea if it is defined + if (!displayObject.hitArea && displayObject.containsPoint) { if (displayObject.containsPoint(point)) { diff --git a/src/loaders/spritesheetParser.js b/src/loaders/spritesheetParser.js index eda9584..4ab9ad3 100644 --- a/src/loaders/spritesheetParser.js +++ b/src/loaders/spritesheetParser.js @@ -22,7 +22,6 @@ const loadOptions = { crossOrigin: resource.crossOrigin, - loadType: Resource.LOAD_TYPE.IMAGE, metadata: resource.metadata.imageMetadata, parentResource: resource, }; @@ -32,6 +31,13 @@ // load the image for this sheet this.add(imageResourceName, resourcePath, loadOptions, function onImageLoad(res) { + if (res.error) + { + next(res.error); + + return; + } + const spritesheet = new Spritesheet( res.texture.baseTexture, resource.data, diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 7006a3e..25659cf 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -92,7 +92,7 @@ * * @member {number} */ - this.canvasPadding = 0; + this.canvasPadding = core.settings.MESH_CANVAS_PADDING; /** * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts diff --git a/src/mesh/NineSlicePlane.js b/src/mesh/NineSlicePlane.js index f0d7575..b4ee32e 100644 --- a/src/mesh/NineSlicePlane.js +++ b/src/mesh/NineSlicePlane.js @@ -143,6 +143,7 @@ const context = renderer.context; context.globalAlpha = this.worldAlpha; + renderer.setBlendMode(this.blendMode); const transform = this.worldTransform; const res = renderer.resolution; diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 6eaf2e0..6b65d4e 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -54,6 +54,7 @@ ); } + renderer.context.globalAlpha = mesh.worldAlpha; renderer.setBlendMode(mesh.blendMode); if (mesh.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) @@ -170,10 +171,12 @@ let y1 = vertices[index1 + 1]; let y2 = vertices[index2 + 1]; - if (mesh.canvasPadding > 0) + const canvasPadding = mesh.canvasPadding / this.renderer.resolution; + + if (canvasPadding > 0) { - const paddingX = mesh.canvasPadding / mesh.worldTransform.a; - const paddingY = mesh.canvasPadding / mesh.worldTransform.d; + const paddingX = canvasPadding / Math.abs(mesh.worldTransform.a); + const paddingY = canvasPadding / Math.abs(mesh.worldTransform.d); const centerX = (x0 + x1 + x2) / 3; const centerY = (y0 + y1 + y2) / 3; diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 40c9361..5827c3b 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -32,13 +32,14 @@ * @param {number} [maxSize=1500] - The maximum number of particles that can be rendered by the container. * Affects size of allocated buffers. * @param {object} [properties] - The properties of children that should be uploaded to the gpu and applied. - * @param {boolean} [properties.scale=false] - When true, scale be uploaded and applied. + * @param {boolean} [properties.vertices=false] - When true, vertices be uploaded and applied. + * if sprite's ` scale/anchor/trim/frame/orig` is dynamic, please set `true`. * @param {boolean} [properties.position=true] - When true, position be uploaded and applied. * @param {boolean} [properties.rotation=false] - When true, rotation be uploaded and applied. * @param {boolean} [properties.uvs=false] - When true, uvs be uploaded and applied. * @param {boolean} [properties.tint=false] - When true, alpha and tint be uploaded and applied. * @param {number} [batchSize=16384] - Number of particles per batch. If less than maxSize, it uses maxSize instead. - * @param {boolean} [autoResize=true] If true, container allocates more batches in case + * @param {boolean} [autoResize=false] If true, container allocates more batches in case * there are more than `maxSize` particles. */ constructor(maxSize = 1500, properties, batchSize = 16384, autoResize = false) @@ -156,12 +157,13 @@ { if (properties) { - this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[0] = 'vertices' in properties || 'scale' in properties + ? !!properties.vertices || !!properties.scale : this._properties[0]; this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; - this._properties[4] = 'alpha' in properties || 'tint' in properties - ? !!properties.alpha || !!properties.tint : this._properties[4]; + this._properties[4] = 'tint' in properties || 'alpha' in properties + ? !!properties.tint || !!properties.alpha : this._properties[4]; } } diff --git a/src/particles/webgl/ParticleShader.js b/src/particles/webgl/ParticleShader.js index d536190..17d5f03 100644 --- a/src/particles/webgl/ParticleShader.js +++ b/src/particles/webgl/ParticleShader.js @@ -21,7 +21,6 @@ 'attribute vec4 aColor;', 'attribute vec2 aPositionCoord;', - 'attribute vec2 aScale;', 'attribute float aRotation;', 'uniform mat3 projectionMatrix;', diff --git a/test/core/Application.js b/test/core/Application.js index 6d89c36..2bcec82 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -48,4 +48,22 @@ done(); }); }); + + it('should be able to destroy filter manager gracefully', function () + { + const app = new PIXI.Application(); + + document.body.appendChild(app.view); + + const sprite = new PIXI.Sprite(PIXI.Texture.WHITE); + + app.stage.addChild(sprite); + + const filter = new PIXI.filters.AlphaFilter(); + + sprite.filters = [filter]; + app.render(); + + app.destroy(true); + }); }); diff --git a/test/core/Graphics.js b/test/core/Graphics.js index 505df4c..0300129 100644 --- a/test/core/Graphics.js +++ b/test/core/Graphics.js @@ -1,6 +1,5 @@ 'use strict'; -const MockPointer = require('../interaction/MockPointer'); const withGL = require('../withGL'); describe('PIXI.Graphics', function () @@ -244,115 +243,8 @@ }); }); - describe('mask', function () + describe('fastRect', function () { - it('should trigger interaction callback when no mask present', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should trigger interaction callback when mask uses beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.beginFill(); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should not trigger interaction callback when mask doesn\'t use beginFill', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.not.been.called; - }); - - it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = mask; - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - - it('should trigger interaction callback when mask is a sprite', function () - { - const stage = new PIXI.Container(); - const pointer = new MockPointer(stage); - const graphics = new PIXI.Graphics(); - const mask = new PIXI.Graphics(); - const spy = sinon.spy(); - - graphics.interactive = true; - graphics.beginFill(0xFF0000); - graphics.drawRect(0, 0, 50, 50); - graphics.on('click', spy); - stage.addChild(graphics); - mask.drawRect(0, 0, 50, 50); - graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); - - pointer.click(10, 10); - - expect(spy).to.have.been.calledOnce; - }); - it('should calculate tint, alpha and blendMode of fastRect correctly', withGL(function () { const renderer = new PIXI.WebGLRenderer(200, 200, {}); diff --git a/test/core/Spritesheet.js b/test/core/Spritesheet.js index dccde04..2ee1136 100644 --- a/test/core/Spritesheet.js +++ b/test/core/Spritesheet.js @@ -27,6 +27,32 @@ done(); }); }; + + this.parseFrame = function (frameData, callback) + { + const data = { + frames: { frame: frameData }, + meta: { scale: 1 }, + }; + const baseTexture = PIXI.BaseTexture.fromCanvas( + document.createElement('canvas') + ); + + baseTexture.imageUrl = 'test.png'; + + const sheet = new PIXI.Spritesheet(baseTexture, data); + + sheet.parse(() => + { + const { frame } = sheet.textures; + + expect(frame).to.be.instanceof(PIXI.Texture); + + callback(frame); + + sheet.destroy(true); + }); + }; }); it('should exist on PIXI', function () @@ -102,4 +128,86 @@ this.validate(spritesheet, done); }; }); + + it('should parse full data untrimmed', function (done) + { + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 14, h: 16 }, + sourceSize: { w: 14, h: 16 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(16); + done(); + }); + }); + + it('should parse texture from trimmed', function (done) + { + const data = { + frame: { x: 0, y: 28, w: 14, h: 14 }, + rotated: false, + trimmed: true, + spriteSourceSize: { x: 0, y: 0, w: 40, h: 20 }, + sourceSize: { w: 40, h: 20 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(40); + expect(texture.height).to.equal(20); + done(); + }); + }); + + it('should parse texture from minimal data', function (done) + { + const data = { frame: { x: 0, y: 0, w: 14, h: 14 } }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse texture without trimmed or sourceSize', function (done) + { + const data = { + frame: { x: 0, y: 14, w: 14, h: 14 }, + rotated: false, + trimmed: false, + spriteSourceSize: { x: 0, y: 0, w: 20, h: 30 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(14); + expect(texture.height).to.equal(14); + done(); + }); + }); + + it('should parse as trimmed if spriteSourceSize is set', function (done) + { + // shoebox format + const data = { + frame: { x: 0, y: 0, w: 14, h: 16 }, + spriteSourceSize: { x: 0, y: 0, w: 120, h: 100 }, + sourceSize: { w: 120, h: 100 }, + }; + + this.parseFrame(data, (texture) => + { + expect(texture.width).to.equal(120); + expect(texture.height).to.equal(100); + done(); + }); + }); }); diff --git a/test/interaction/InteractionManager.js b/test/interaction/InteractionManager.js index 136640e..4676252 100644 --- a/test/interaction/InteractionManager.js +++ b/test/interaction/InteractionManager.js @@ -1087,6 +1087,248 @@ }); }); + describe('masks', function () + { + it('should trigger interaction callback when no mask present', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask uses beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents mask', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + mask.beginFill(); + mask.drawRect(0, 0, 25, 25); + parent.mask = mask; + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should not trigger interaction callback when mask doesn\'t use beginFill', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.not.been.called; + }); + + it('should trigger interaction callback when mask doesn\'t use beginFill but hitArea is defined', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.hitArea = new PIXI.Rectangle(0, 0, 50, 50); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = mask; + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should trigger interaction callback when mask is a sprite', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const mask = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + mask.drawRect(0, 0, 50, 50); + graphics.mask = new PIXI.Sprite(mask.generateCanvasTexture()); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + }); + + describe('hitArea', function () + { + it('should trigger interaction callback when within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback when not within hitArea', function () + { + const stage = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(graphics); + graphics.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + + it('should trigger interaction callback on child when inside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(10, 10); + + expect(spy).to.have.been.calledOnce; + }); + + it('should not trigger interaction callback on child when outside of parents hitArea', function () + { + const stage = new PIXI.Container(); + const parent = new PIXI.Container(); + const pointer = new MockPointer(stage); + const graphics = new PIXI.Graphics(); + const spy = sinon.spy(); + + graphics.interactive = true; + graphics.beginFill(0xFF0000); + graphics.drawRect(0, 0, 50, 50); + graphics.on('click', spy); + stage.addChild(parent); + parent.addChild(graphics); + parent.hitArea = new PIXI.Rectangle(0, 0, 25, 25); + + pointer.click(30, 30); + + expect(spy).to.have.not.been.calledOnce; + }); + }); + describe('cursor changes', function () { it('cursor should be the cursor of interactive item', function () diff --git a/test/loaders/resources/atlas.crn b/test/loaders/resources/atlas.crn new file mode 100644 index 0000000..d5e7892 --- /dev/null +++ b/test/loaders/resources/atlas.crn Binary files differ diff --git a/test/loaders/resources/atlas_crn.json b/test/loaders/resources/atlas_crn.json new file mode 100644 index 0000000..6327c0b --- /dev/null +++ b/test/loaders/resources/atlas_crn.json @@ -0,0 +1,25 @@ +{ + "meta": { + "image": "atlas.crn", + "size": {"w":256,"h":256}, + "scale": "1" + }, + "frames": { + "resources/test.png": + { + "frame": {"x":2,"y":2,"w":152,"h":188}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":74,"y":36,"w":152,"h":188}, + "sourceSize": {"w":300,"h":225} + }, + "resources/font.png": + { + "frame": {"x":158,"y":2,"w":40,"h":42}, + "rotated": false, + "trimmed": true, + "spriteSourceSize": {"x":2,"y":2,"w":40,"h":42}, + "sourceSize": {"w":43,"h":46} + } + } +} \ No newline at end of file diff --git a/test/loaders/resources/atlas_error.json b/test/loaders/resources/atlas_error.json new file mode 100644 index 0000000..531a124 --- /dev/null +++ b/test/loaders/resources/atlas_error.json @@ -0,0 +1,17 @@ +{ + "frames": { + "boss1.png": { + "frame": {"x":1,"y":1,"w":168,"h":168}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":168,"h":168}, + "sourceSize": {"w":168,"h":168} + } + }, + "meta": { + "image": "invalid.png", + "format": "RGBA8888", + "size": {"w":170,"h":170}, + "scale": "1" + } +} \ No newline at end of file diff --git a/test/loaders/spritesheetParser.js b/test/loaders/spritesheetParser.js index 4d54805..7d0d0c1 100644 --- a/test/loaders/spritesheetParser.js +++ b/test/loaders/spritesheetParser.js @@ -60,6 +60,52 @@ .that.is.an.instanceof(PIXI.Texture); }); + it('should not load binary images as an image loader type', function (done) + { + const loader = new PIXI.loaders.Loader(); + + // provide a mock pre-loader that creates an empty base texture for compressed texture assets + // this is necessary because the spritesheetParser expects a baseTexture on the resource + loader.pre((resource, next) => + { + if (resource.extension === 'crn') + { + resource.texture = PIXI.Texture.EMPTY; + } + next(); + }) + .add(`atlas_crn`, path.join(__dirname, 'resources', 'atlas_crn.json')) + .add(`atlas`, path.join(__dirname, 'resources', 'atlas.json')) + .load((loader, resources) => + { + expect(resources.atlas_image.data).to.be.instanceof(HTMLImageElement); + expect(resources.atlas_crn_image.data).to.not.be.instanceof(HTMLImageElement); + loader.reset(); + done(); + }); + }); + + it('should dispatch an error failing to load spritesheet image', function (done) + { + const spy = sinon.spy((error, ldr, res) => + { + expect(res.name).to.equal('atlas_image'); + expect(res.error).to.equal(error); + expect(error.toString()).to.have.string('Failed to load element using: IMG'); + }); + const loader = new PIXI.loaders.Loader(); + + loader.add('atlas', path.join(__dirname, 'resources', 'atlas_error.json')); + loader.onError.add(spy); + loader.load((loader, resources) => + { + expect(resources.atlas_image.error).to.be.instanceof(Error); + expect(spy.calledOnce).to.be.true; + loader.reset(); + done(); + }); + }); + it('should build the image url', function () { function getResourcePath(url, image)