diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 71f31e2..c682a36 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -32,6 +32,7 @@ trim: false, wordWrap: false, wordWrapWidth: 100, + leading: 0, }; /** @@ -53,7 +54,7 @@ * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius - * @param {string} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient @@ -70,6 +71,7 @@ * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps') * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', * '200', '300', '400', '500', '600', '700', 800' or '900') + * @param {number} [style.leading=0] - The space between lines * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0 * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve @@ -120,11 +122,16 @@ Object.assign(this, defaultStyle); } + /** + * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text + * + * @member {string} + */ get align() { return this._align; } - set align(align) + set align(align) // eslint-disable-line require-jsdoc { if (this._align !== align) { @@ -133,11 +140,16 @@ } } + /** + * Indicates if lines can be wrapped within words, it needs wordWrap to be set to true + * + * @member {boolean} + */ get breakWords() { return this._breakWords; } - set breakWords(breakWords) + set breakWords(breakWords) // eslint-disable-line require-jsdoc { if (this._breakWords !== breakWords) { @@ -146,11 +158,16 @@ } } + /** + * Set a drop shadow for the text + * + * @member {boolean} + */ get dropShadow() { return this._dropShadow; } - set dropShadow(dropShadow) + set dropShadow(dropShadow) // eslint-disable-line require-jsdoc { if (this._dropShadow !== dropShadow) { @@ -159,11 +176,16 @@ } } + /** + * Set alpha for the drop shadow + * + * @member {number} + */ get dropShadowAlpha() { return this._dropShadowAlpha; } - set dropShadowAlpha(dropShadowAlpha) + set dropShadowAlpha(dropShadowAlpha) // eslint-disable-line require-jsdoc { if (this._dropShadowAlpha !== dropShadowAlpha) { @@ -172,11 +194,16 @@ } } + /** + * Set a angle of the drop shadow + * + * @member {number} + */ get dropShadowAngle() { return this._dropShadowAngle; } - set dropShadowAngle(dropShadowAngle) + set dropShadowAngle(dropShadowAngle) // eslint-disable-line require-jsdoc { if (this._dropShadowAngle !== dropShadowAngle) { @@ -185,11 +212,16 @@ } } + /** + * Set a shadow blur radius + * + * @member {number} + */ get dropShadowBlur() { return this._dropShadowBlur; } - set dropShadowBlur(dropShadowBlur) + set dropShadowBlur(dropShadowBlur) // eslint-disable-line require-jsdoc { if (this._dropShadowBlur !== dropShadowBlur) { @@ -198,11 +230,16 @@ } } + /** + * A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * + * @member {string|number} + */ get dropShadowColor() { return this._dropShadowColor; } - set dropShadowColor(dropShadowColor) + set dropShadowColor(dropShadowColor) // eslint-disable-line require-jsdoc { const outputColor = getColor(dropShadowColor); if (this._dropShadowColor !== outputColor) @@ -212,11 +249,16 @@ } } + /** + * Set a distance of the drop shadow + * + * @member {number} + */ get dropShadowDistance() { return this._dropShadowDistance; } - set dropShadowDistance(dropShadowDistance) + set dropShadowDistance(dropShadowDistance) // eslint-disable-line require-jsdoc { if (this._dropShadowDistance !== dropShadowDistance) { @@ -225,11 +267,18 @@ } } + /** + * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'. + * Can be an array to create a gradient eg ['#000000','#FFFFFF'] + * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} + * + * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern} + */ get fill() { return this._fill; } - set fill(fill) + set fill(fill) // eslint-disable-line require-jsdoc { const outputColor = getColor(fill); if (this._fill !== outputColor) @@ -239,11 +288,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient. + * See {@link PIXI.TEXT_GRADIENT} + * + * @member {number} + */ get fillGradientType() { return this._fillGradientType; } - set fillGradientType(fillGradientType) + set fillGradientType(fillGradientType) // eslint-disable-line require-jsdoc { if (this._fillGradientType !== fillGradientType) { @@ -252,11 +307,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this array can set the stop points + * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. + * + * @member {number[]} + */ get fillGradientStops() { return this._fillGradientStops; } - set fillGradientStops(fillGradientStops) + set fillGradientStops(fillGradientStops) // eslint-disable-line require-jsdoc { if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) { @@ -265,11 +326,16 @@ } } + /** + * The font family + * + * @member {string|string[]} + */ get fontFamily() { return this._fontFamily; } - set fontFamily(fontFamily) + set fontFamily(fontFamily) // eslint-disable-line require-jsdoc { if (this.fontFamily !== fontFamily) { @@ -278,11 +344,17 @@ } } + /** + * The font size + * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * + * @member {number|string} + */ get fontSize() { return this._fontSize; } - set fontSize(fontSize) + set fontSize(fontSize) // eslint-disable-line require-jsdoc { if (this._fontSize !== fontSize) { @@ -291,11 +363,17 @@ } } + /** + * The font style + * ('normal', 'italic' or 'oblique') + * + * @member {string} + */ get fontStyle() { return this._fontStyle; } - set fontStyle(fontStyle) + set fontStyle(fontStyle) // eslint-disable-line require-jsdoc { if (this._fontStyle !== fontStyle) { @@ -304,11 +382,17 @@ } } + /** + * The font variant + * ('normal' or 'small-caps') + * + * @member {string} + */ get fontVariant() { return this._fontVariant; } - set fontVariant(fontVariant) + set fontVariant(fontVariant) // eslint-disable-line require-jsdoc { if (this._fontVariant !== fontVariant) { @@ -317,11 +401,17 @@ } } + /** + * The font weight + * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') + * + * @member {string} + */ get fontWeight() { return this._fontWeight; } - set fontWeight(fontWeight) + set fontWeight(fontWeight) // eslint-disable-line require-jsdoc { if (this._fontWeight !== fontWeight) { @@ -330,11 +420,16 @@ } } + /** + * The amount of spacing between letters, default is 0 + * + * @member {number} + */ get letterSpacing() { return this._letterSpacing; } - set letterSpacing(letterSpacing) + set letterSpacing(letterSpacing) // eslint-disable-line require-jsdoc { if (this._letterSpacing !== letterSpacing) { @@ -343,11 +438,16 @@ } } + /** + * The line height, a number that represents the vertical space that a letter uses + * + * @member {number} + */ get lineHeight() { return this._lineHeight; } - set lineHeight(lineHeight) + set lineHeight(lineHeight) // eslint-disable-line require-jsdoc { if (this._lineHeight !== lineHeight) { @@ -356,11 +456,35 @@ } } + /** + * The space between lines + * + * @member {number} + */ + get leading() + { + return this._leading; + } + set leading(leading) // eslint-disable-line require-jsdoc + { + if (this._leading !== leading) + { + this._leading = leading; + this.styleID++; + } + } + + /** + * The lineJoin property sets the type of corner created, it can resolve spiked text issues. + * Default is 'miter' (creates a sharp corner). + * + * @member {string} + */ get lineJoin() { return this._lineJoin; } - set lineJoin(lineJoin) + set lineJoin(lineJoin) // eslint-disable-line require-jsdoc { if (this._lineJoin !== lineJoin) { @@ -369,11 +493,17 @@ } } + /** + * The miter limit to use when using the 'miter' lineJoin mode + * This can reduce or increase the spikiness of rendered text. + * + * @member {number} + */ get miterLimit() { return this._miterLimit; } - set miterLimit(miterLimit) + set miterLimit(miterLimit) // eslint-disable-line require-jsdoc { if (this._miterLimit !== miterLimit) { @@ -382,11 +512,17 @@ } } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * + * @member {number} + */ get padding() { return this._padding; } - set padding(padding) + set padding(padding) // eslint-disable-line require-jsdoc { if (this._padding !== padding) { @@ -395,11 +531,17 @@ } } + /** + * A canvas fillstyle that will be used on the text stroke + * e.g 'blue', '#FCFF00' + * + * @member {string|number} + */ get stroke() { return this._stroke; } - set stroke(stroke) + set stroke(stroke) // eslint-disable-line require-jsdoc { const outputColor = getColor(stroke); if (this._stroke !== outputColor) @@ -409,11 +551,17 @@ } } + /** + * A number that represents the thickness of the stroke. + * Default is 0 (no stroke) + * + * @member {number} + */ get strokeThickness() { return this._strokeThickness; } - set strokeThickness(strokeThickness) + set strokeThickness(strokeThickness) // eslint-disable-line require-jsdoc { if (this._strokeThickness !== strokeThickness) { @@ -422,11 +570,16 @@ } } + /** + * The baseline of the text that is rendered. + * + * @member {string} + */ get textBaseline() { return this._textBaseline; } - set textBaseline(textBaseline) + set textBaseline(textBaseline) // eslint-disable-line require-jsdoc { if (this._textBaseline !== textBaseline) { @@ -435,11 +588,16 @@ } } + /** + * Trim transparent borders + * + * @member {boolean} + */ get trim() { return this._trim; } - set trim(trim) + set trim(trim) // eslint-disable-line require-jsdoc { if (this._trim !== trim) { @@ -448,11 +606,16 @@ } } + /** + * Indicates if word wrap should be used + * + * @member {boolean} + */ get wordWrap() { return this._wordWrap; } - set wordWrap(wordWrap) + set wordWrap(wordWrap) // eslint-disable-line require-jsdoc { if (this._wordWrap !== wordWrap) { @@ -461,11 +624,16 @@ } } + /** + * The width at which text will wrap, it needs wordWrap to be set to true + * + * @member {number} + */ get wordWrapWidth() { return this._wordWrapWidth; } - set wordWrapWidth(wordWrapWidth) + set wordWrapWidth(wordWrapWidth) // eslint-disable-line require-jsdoc { if (this._wordWrapWidth !== wordWrapWidth) { diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 71f31e2..c682a36 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -32,6 +32,7 @@ trim: false, wordWrap: false, wordWrapWidth: 100, + leading: 0, }; /** @@ -53,7 +54,7 @@ * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius - * @param {string} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient @@ -70,6 +71,7 @@ * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps') * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', * '200', '300', '400', '500', '600', '700', 800' or '900') + * @param {number} [style.leading=0] - The space between lines * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0 * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve @@ -120,11 +122,16 @@ Object.assign(this, defaultStyle); } + /** + * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text + * + * @member {string} + */ get align() { return this._align; } - set align(align) + set align(align) // eslint-disable-line require-jsdoc { if (this._align !== align) { @@ -133,11 +140,16 @@ } } + /** + * Indicates if lines can be wrapped within words, it needs wordWrap to be set to true + * + * @member {boolean} + */ get breakWords() { return this._breakWords; } - set breakWords(breakWords) + set breakWords(breakWords) // eslint-disable-line require-jsdoc { if (this._breakWords !== breakWords) { @@ -146,11 +158,16 @@ } } + /** + * Set a drop shadow for the text + * + * @member {boolean} + */ get dropShadow() { return this._dropShadow; } - set dropShadow(dropShadow) + set dropShadow(dropShadow) // eslint-disable-line require-jsdoc { if (this._dropShadow !== dropShadow) { @@ -159,11 +176,16 @@ } } + /** + * Set alpha for the drop shadow + * + * @member {number} + */ get dropShadowAlpha() { return this._dropShadowAlpha; } - set dropShadowAlpha(dropShadowAlpha) + set dropShadowAlpha(dropShadowAlpha) // eslint-disable-line require-jsdoc { if (this._dropShadowAlpha !== dropShadowAlpha) { @@ -172,11 +194,16 @@ } } + /** + * Set a angle of the drop shadow + * + * @member {number} + */ get dropShadowAngle() { return this._dropShadowAngle; } - set dropShadowAngle(dropShadowAngle) + set dropShadowAngle(dropShadowAngle) // eslint-disable-line require-jsdoc { if (this._dropShadowAngle !== dropShadowAngle) { @@ -185,11 +212,16 @@ } } + /** + * Set a shadow blur radius + * + * @member {number} + */ get dropShadowBlur() { return this._dropShadowBlur; } - set dropShadowBlur(dropShadowBlur) + set dropShadowBlur(dropShadowBlur) // eslint-disable-line require-jsdoc { if (this._dropShadowBlur !== dropShadowBlur) { @@ -198,11 +230,16 @@ } } + /** + * A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * + * @member {string|number} + */ get dropShadowColor() { return this._dropShadowColor; } - set dropShadowColor(dropShadowColor) + set dropShadowColor(dropShadowColor) // eslint-disable-line require-jsdoc { const outputColor = getColor(dropShadowColor); if (this._dropShadowColor !== outputColor) @@ -212,11 +249,16 @@ } } + /** + * Set a distance of the drop shadow + * + * @member {number} + */ get dropShadowDistance() { return this._dropShadowDistance; } - set dropShadowDistance(dropShadowDistance) + set dropShadowDistance(dropShadowDistance) // eslint-disable-line require-jsdoc { if (this._dropShadowDistance !== dropShadowDistance) { @@ -225,11 +267,18 @@ } } + /** + * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'. + * Can be an array to create a gradient eg ['#000000','#FFFFFF'] + * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} + * + * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern} + */ get fill() { return this._fill; } - set fill(fill) + set fill(fill) // eslint-disable-line require-jsdoc { const outputColor = getColor(fill); if (this._fill !== outputColor) @@ -239,11 +288,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient. + * See {@link PIXI.TEXT_GRADIENT} + * + * @member {number} + */ get fillGradientType() { return this._fillGradientType; } - set fillGradientType(fillGradientType) + set fillGradientType(fillGradientType) // eslint-disable-line require-jsdoc { if (this._fillGradientType !== fillGradientType) { @@ -252,11 +307,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this array can set the stop points + * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. + * + * @member {number[]} + */ get fillGradientStops() { return this._fillGradientStops; } - set fillGradientStops(fillGradientStops) + set fillGradientStops(fillGradientStops) // eslint-disable-line require-jsdoc { if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) { @@ -265,11 +326,16 @@ } } + /** + * The font family + * + * @member {string|string[]} + */ get fontFamily() { return this._fontFamily; } - set fontFamily(fontFamily) + set fontFamily(fontFamily) // eslint-disable-line require-jsdoc { if (this.fontFamily !== fontFamily) { @@ -278,11 +344,17 @@ } } + /** + * The font size + * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * + * @member {number|string} + */ get fontSize() { return this._fontSize; } - set fontSize(fontSize) + set fontSize(fontSize) // eslint-disable-line require-jsdoc { if (this._fontSize !== fontSize) { @@ -291,11 +363,17 @@ } } + /** + * The font style + * ('normal', 'italic' or 'oblique') + * + * @member {string} + */ get fontStyle() { return this._fontStyle; } - set fontStyle(fontStyle) + set fontStyle(fontStyle) // eslint-disable-line require-jsdoc { if (this._fontStyle !== fontStyle) { @@ -304,11 +382,17 @@ } } + /** + * The font variant + * ('normal' or 'small-caps') + * + * @member {string} + */ get fontVariant() { return this._fontVariant; } - set fontVariant(fontVariant) + set fontVariant(fontVariant) // eslint-disable-line require-jsdoc { if (this._fontVariant !== fontVariant) { @@ -317,11 +401,17 @@ } } + /** + * The font weight + * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') + * + * @member {string} + */ get fontWeight() { return this._fontWeight; } - set fontWeight(fontWeight) + set fontWeight(fontWeight) // eslint-disable-line require-jsdoc { if (this._fontWeight !== fontWeight) { @@ -330,11 +420,16 @@ } } + /** + * The amount of spacing between letters, default is 0 + * + * @member {number} + */ get letterSpacing() { return this._letterSpacing; } - set letterSpacing(letterSpacing) + set letterSpacing(letterSpacing) // eslint-disable-line require-jsdoc { if (this._letterSpacing !== letterSpacing) { @@ -343,11 +438,16 @@ } } + /** + * The line height, a number that represents the vertical space that a letter uses + * + * @member {number} + */ get lineHeight() { return this._lineHeight; } - set lineHeight(lineHeight) + set lineHeight(lineHeight) // eslint-disable-line require-jsdoc { if (this._lineHeight !== lineHeight) { @@ -356,11 +456,35 @@ } } + /** + * The space between lines + * + * @member {number} + */ + get leading() + { + return this._leading; + } + set leading(leading) // eslint-disable-line require-jsdoc + { + if (this._leading !== leading) + { + this._leading = leading; + this.styleID++; + } + } + + /** + * The lineJoin property sets the type of corner created, it can resolve spiked text issues. + * Default is 'miter' (creates a sharp corner). + * + * @member {string} + */ get lineJoin() { return this._lineJoin; } - set lineJoin(lineJoin) + set lineJoin(lineJoin) // eslint-disable-line require-jsdoc { if (this._lineJoin !== lineJoin) { @@ -369,11 +493,17 @@ } } + /** + * The miter limit to use when using the 'miter' lineJoin mode + * This can reduce or increase the spikiness of rendered text. + * + * @member {number} + */ get miterLimit() { return this._miterLimit; } - set miterLimit(miterLimit) + set miterLimit(miterLimit) // eslint-disable-line require-jsdoc { if (this._miterLimit !== miterLimit) { @@ -382,11 +512,17 @@ } } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * + * @member {number} + */ get padding() { return this._padding; } - set padding(padding) + set padding(padding) // eslint-disable-line require-jsdoc { if (this._padding !== padding) { @@ -395,11 +531,17 @@ } } + /** + * A canvas fillstyle that will be used on the text stroke + * e.g 'blue', '#FCFF00' + * + * @member {string|number} + */ get stroke() { return this._stroke; } - set stroke(stroke) + set stroke(stroke) // eslint-disable-line require-jsdoc { const outputColor = getColor(stroke); if (this._stroke !== outputColor) @@ -409,11 +551,17 @@ } } + /** + * A number that represents the thickness of the stroke. + * Default is 0 (no stroke) + * + * @member {number} + */ get strokeThickness() { return this._strokeThickness; } - set strokeThickness(strokeThickness) + set strokeThickness(strokeThickness) // eslint-disable-line require-jsdoc { if (this._strokeThickness !== strokeThickness) { @@ -422,11 +570,16 @@ } } + /** + * The baseline of the text that is rendered. + * + * @member {string} + */ get textBaseline() { return this._textBaseline; } - set textBaseline(textBaseline) + set textBaseline(textBaseline) // eslint-disable-line require-jsdoc { if (this._textBaseline !== textBaseline) { @@ -435,11 +588,16 @@ } } + /** + * Trim transparent borders + * + * @member {boolean} + */ get trim() { return this._trim; } - set trim(trim) + set trim(trim) // eslint-disable-line require-jsdoc { if (this._trim !== trim) { @@ -448,11 +606,16 @@ } } + /** + * Indicates if word wrap should be used + * + * @member {boolean} + */ get wordWrap() { return this._wordWrap; } - set wordWrap(wordWrap) + set wordWrap(wordWrap) // eslint-disable-line require-jsdoc { if (this._wordWrap !== wordWrap) { @@ -461,11 +624,16 @@ } } + /** + * The width at which text will wrap, it needs wordWrap to be set to true + * + * @member {number} + */ get wordWrapWidth() { return this._wordWrapWidth; } - set wordWrapWidth(wordWrapWidth) + set wordWrapWidth(wordWrapWidth) // eslint-disable-line require-jsdoc { if (this._wordWrapWidth !== wordWrapWidth) { diff --git a/src/core/textures/Texture.js b/src/core/textures/Texture.js index 3922e52..3a472be 100644 --- a/src/core/textures/Texture.js +++ b/src/core/textures/Texture.js @@ -521,7 +521,11 @@ { for (let i = 0; i < texture.textureCacheIds.length; ++i) { - delete TextureCache[texture.textureCacheIds[i]]; + // Check that texture matches the one being passed in before deleting it from the cache. + if (TextureCache[texture.textureCacheIds[i]] === texture) + { + delete TextureCache[texture.textureCacheIds[i]]; + } } texture.textureCacheIds.length = 0; diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 71f31e2..c682a36 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -32,6 +32,7 @@ trim: false, wordWrap: false, wordWrapWidth: 100, + leading: 0, }; /** @@ -53,7 +54,7 @@ * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius - * @param {string} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient @@ -70,6 +71,7 @@ * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps') * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', * '200', '300', '400', '500', '600', '700', 800' or '900') + * @param {number} [style.leading=0] - The space between lines * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0 * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve @@ -120,11 +122,16 @@ Object.assign(this, defaultStyle); } + /** + * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text + * + * @member {string} + */ get align() { return this._align; } - set align(align) + set align(align) // eslint-disable-line require-jsdoc { if (this._align !== align) { @@ -133,11 +140,16 @@ } } + /** + * Indicates if lines can be wrapped within words, it needs wordWrap to be set to true + * + * @member {boolean} + */ get breakWords() { return this._breakWords; } - set breakWords(breakWords) + set breakWords(breakWords) // eslint-disable-line require-jsdoc { if (this._breakWords !== breakWords) { @@ -146,11 +158,16 @@ } } + /** + * Set a drop shadow for the text + * + * @member {boolean} + */ get dropShadow() { return this._dropShadow; } - set dropShadow(dropShadow) + set dropShadow(dropShadow) // eslint-disable-line require-jsdoc { if (this._dropShadow !== dropShadow) { @@ -159,11 +176,16 @@ } } + /** + * Set alpha for the drop shadow + * + * @member {number} + */ get dropShadowAlpha() { return this._dropShadowAlpha; } - set dropShadowAlpha(dropShadowAlpha) + set dropShadowAlpha(dropShadowAlpha) // eslint-disable-line require-jsdoc { if (this._dropShadowAlpha !== dropShadowAlpha) { @@ -172,11 +194,16 @@ } } + /** + * Set a angle of the drop shadow + * + * @member {number} + */ get dropShadowAngle() { return this._dropShadowAngle; } - set dropShadowAngle(dropShadowAngle) + set dropShadowAngle(dropShadowAngle) // eslint-disable-line require-jsdoc { if (this._dropShadowAngle !== dropShadowAngle) { @@ -185,11 +212,16 @@ } } + /** + * Set a shadow blur radius + * + * @member {number} + */ get dropShadowBlur() { return this._dropShadowBlur; } - set dropShadowBlur(dropShadowBlur) + set dropShadowBlur(dropShadowBlur) // eslint-disable-line require-jsdoc { if (this._dropShadowBlur !== dropShadowBlur) { @@ -198,11 +230,16 @@ } } + /** + * A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * + * @member {string|number} + */ get dropShadowColor() { return this._dropShadowColor; } - set dropShadowColor(dropShadowColor) + set dropShadowColor(dropShadowColor) // eslint-disable-line require-jsdoc { const outputColor = getColor(dropShadowColor); if (this._dropShadowColor !== outputColor) @@ -212,11 +249,16 @@ } } + /** + * Set a distance of the drop shadow + * + * @member {number} + */ get dropShadowDistance() { return this._dropShadowDistance; } - set dropShadowDistance(dropShadowDistance) + set dropShadowDistance(dropShadowDistance) // eslint-disable-line require-jsdoc { if (this._dropShadowDistance !== dropShadowDistance) { @@ -225,11 +267,18 @@ } } + /** + * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'. + * Can be an array to create a gradient eg ['#000000','#FFFFFF'] + * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} + * + * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern} + */ get fill() { return this._fill; } - set fill(fill) + set fill(fill) // eslint-disable-line require-jsdoc { const outputColor = getColor(fill); if (this._fill !== outputColor) @@ -239,11 +288,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient. + * See {@link PIXI.TEXT_GRADIENT} + * + * @member {number} + */ get fillGradientType() { return this._fillGradientType; } - set fillGradientType(fillGradientType) + set fillGradientType(fillGradientType) // eslint-disable-line require-jsdoc { if (this._fillGradientType !== fillGradientType) { @@ -252,11 +307,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this array can set the stop points + * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. + * + * @member {number[]} + */ get fillGradientStops() { return this._fillGradientStops; } - set fillGradientStops(fillGradientStops) + set fillGradientStops(fillGradientStops) // eslint-disable-line require-jsdoc { if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) { @@ -265,11 +326,16 @@ } } + /** + * The font family + * + * @member {string|string[]} + */ get fontFamily() { return this._fontFamily; } - set fontFamily(fontFamily) + set fontFamily(fontFamily) // eslint-disable-line require-jsdoc { if (this.fontFamily !== fontFamily) { @@ -278,11 +344,17 @@ } } + /** + * The font size + * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * + * @member {number|string} + */ get fontSize() { return this._fontSize; } - set fontSize(fontSize) + set fontSize(fontSize) // eslint-disable-line require-jsdoc { if (this._fontSize !== fontSize) { @@ -291,11 +363,17 @@ } } + /** + * The font style + * ('normal', 'italic' or 'oblique') + * + * @member {string} + */ get fontStyle() { return this._fontStyle; } - set fontStyle(fontStyle) + set fontStyle(fontStyle) // eslint-disable-line require-jsdoc { if (this._fontStyle !== fontStyle) { @@ -304,11 +382,17 @@ } } + /** + * The font variant + * ('normal' or 'small-caps') + * + * @member {string} + */ get fontVariant() { return this._fontVariant; } - set fontVariant(fontVariant) + set fontVariant(fontVariant) // eslint-disable-line require-jsdoc { if (this._fontVariant !== fontVariant) { @@ -317,11 +401,17 @@ } } + /** + * The font weight + * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') + * + * @member {string} + */ get fontWeight() { return this._fontWeight; } - set fontWeight(fontWeight) + set fontWeight(fontWeight) // eslint-disable-line require-jsdoc { if (this._fontWeight !== fontWeight) { @@ -330,11 +420,16 @@ } } + /** + * The amount of spacing between letters, default is 0 + * + * @member {number} + */ get letterSpacing() { return this._letterSpacing; } - set letterSpacing(letterSpacing) + set letterSpacing(letterSpacing) // eslint-disable-line require-jsdoc { if (this._letterSpacing !== letterSpacing) { @@ -343,11 +438,16 @@ } } + /** + * The line height, a number that represents the vertical space that a letter uses + * + * @member {number} + */ get lineHeight() { return this._lineHeight; } - set lineHeight(lineHeight) + set lineHeight(lineHeight) // eslint-disable-line require-jsdoc { if (this._lineHeight !== lineHeight) { @@ -356,11 +456,35 @@ } } + /** + * The space between lines + * + * @member {number} + */ + get leading() + { + return this._leading; + } + set leading(leading) // eslint-disable-line require-jsdoc + { + if (this._leading !== leading) + { + this._leading = leading; + this.styleID++; + } + } + + /** + * The lineJoin property sets the type of corner created, it can resolve spiked text issues. + * Default is 'miter' (creates a sharp corner). + * + * @member {string} + */ get lineJoin() { return this._lineJoin; } - set lineJoin(lineJoin) + set lineJoin(lineJoin) // eslint-disable-line require-jsdoc { if (this._lineJoin !== lineJoin) { @@ -369,11 +493,17 @@ } } + /** + * The miter limit to use when using the 'miter' lineJoin mode + * This can reduce or increase the spikiness of rendered text. + * + * @member {number} + */ get miterLimit() { return this._miterLimit; } - set miterLimit(miterLimit) + set miterLimit(miterLimit) // eslint-disable-line require-jsdoc { if (this._miterLimit !== miterLimit) { @@ -382,11 +512,17 @@ } } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * + * @member {number} + */ get padding() { return this._padding; } - set padding(padding) + set padding(padding) // eslint-disable-line require-jsdoc { if (this._padding !== padding) { @@ -395,11 +531,17 @@ } } + /** + * A canvas fillstyle that will be used on the text stroke + * e.g 'blue', '#FCFF00' + * + * @member {string|number} + */ get stroke() { return this._stroke; } - set stroke(stroke) + set stroke(stroke) // eslint-disable-line require-jsdoc { const outputColor = getColor(stroke); if (this._stroke !== outputColor) @@ -409,11 +551,17 @@ } } + /** + * A number that represents the thickness of the stroke. + * Default is 0 (no stroke) + * + * @member {number} + */ get strokeThickness() { return this._strokeThickness; } - set strokeThickness(strokeThickness) + set strokeThickness(strokeThickness) // eslint-disable-line require-jsdoc { if (this._strokeThickness !== strokeThickness) { @@ -422,11 +570,16 @@ } } + /** + * The baseline of the text that is rendered. + * + * @member {string} + */ get textBaseline() { return this._textBaseline; } - set textBaseline(textBaseline) + set textBaseline(textBaseline) // eslint-disable-line require-jsdoc { if (this._textBaseline !== textBaseline) { @@ -435,11 +588,16 @@ } } + /** + * Trim transparent borders + * + * @member {boolean} + */ get trim() { return this._trim; } - set trim(trim) + set trim(trim) // eslint-disable-line require-jsdoc { if (this._trim !== trim) { @@ -448,11 +606,16 @@ } } + /** + * Indicates if word wrap should be used + * + * @member {boolean} + */ get wordWrap() { return this._wordWrap; } - set wordWrap(wordWrap) + set wordWrap(wordWrap) // eslint-disable-line require-jsdoc { if (this._wordWrap !== wordWrap) { @@ -461,11 +624,16 @@ } } + /** + * The width at which text will wrap, it needs wordWrap to be set to true + * + * @member {number} + */ get wordWrapWidth() { return this._wordWrapWidth; } - set wordWrapWidth(wordWrapWidth) + set wordWrapWidth(wordWrapWidth) // eslint-disable-line require-jsdoc { if (this._wordWrapWidth !== wordWrapWidth) { diff --git a/src/core/textures/Texture.js b/src/core/textures/Texture.js index 3922e52..3a472be 100644 --- a/src/core/textures/Texture.js +++ b/src/core/textures/Texture.js @@ -521,7 +521,11 @@ { for (let i = 0; i < texture.textureCacheIds.length; ++i) { - delete TextureCache[texture.textureCacheIds[i]]; + // Check that texture matches the one being passed in before deleting it from the cache. + if (TextureCache[texture.textureCacheIds[i]] === texture) + { + delete TextureCache[texture.textureCacheIds[i]]; + } } texture.textureCacheIds.length = 0; diff --git a/src/core/ticker/Ticker.js b/src/core/ticker/Ticker.js index 1d58724..e07e0a6 100644 --- a/src/core/ticker/Ticker.js +++ b/src/core/ticker/Ticker.js @@ -81,9 +81,9 @@ * this value will have a precision of 1 µs. * * @member {number} - * @default 0 + * @default -1 */ - this.lastTime = 0; + this.lastTime = -1; /** * Factor of current {@link PIXI.ticker.Ticker#deltaTime}. diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 71f31e2..c682a36 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -32,6 +32,7 @@ trim: false, wordWrap: false, wordWrapWidth: 100, + leading: 0, }; /** @@ -53,7 +54,7 @@ * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius - * @param {string} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient @@ -70,6 +71,7 @@ * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps') * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', * '200', '300', '400', '500', '600', '700', 800' or '900') + * @param {number} [style.leading=0] - The space between lines * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0 * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve @@ -120,11 +122,16 @@ Object.assign(this, defaultStyle); } + /** + * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text + * + * @member {string} + */ get align() { return this._align; } - set align(align) + set align(align) // eslint-disable-line require-jsdoc { if (this._align !== align) { @@ -133,11 +140,16 @@ } } + /** + * Indicates if lines can be wrapped within words, it needs wordWrap to be set to true + * + * @member {boolean} + */ get breakWords() { return this._breakWords; } - set breakWords(breakWords) + set breakWords(breakWords) // eslint-disable-line require-jsdoc { if (this._breakWords !== breakWords) { @@ -146,11 +158,16 @@ } } + /** + * Set a drop shadow for the text + * + * @member {boolean} + */ get dropShadow() { return this._dropShadow; } - set dropShadow(dropShadow) + set dropShadow(dropShadow) // eslint-disable-line require-jsdoc { if (this._dropShadow !== dropShadow) { @@ -159,11 +176,16 @@ } } + /** + * Set alpha for the drop shadow + * + * @member {number} + */ get dropShadowAlpha() { return this._dropShadowAlpha; } - set dropShadowAlpha(dropShadowAlpha) + set dropShadowAlpha(dropShadowAlpha) // eslint-disable-line require-jsdoc { if (this._dropShadowAlpha !== dropShadowAlpha) { @@ -172,11 +194,16 @@ } } + /** + * Set a angle of the drop shadow + * + * @member {number} + */ get dropShadowAngle() { return this._dropShadowAngle; } - set dropShadowAngle(dropShadowAngle) + set dropShadowAngle(dropShadowAngle) // eslint-disable-line require-jsdoc { if (this._dropShadowAngle !== dropShadowAngle) { @@ -185,11 +212,16 @@ } } + /** + * Set a shadow blur radius + * + * @member {number} + */ get dropShadowBlur() { return this._dropShadowBlur; } - set dropShadowBlur(dropShadowBlur) + set dropShadowBlur(dropShadowBlur) // eslint-disable-line require-jsdoc { if (this._dropShadowBlur !== dropShadowBlur) { @@ -198,11 +230,16 @@ } } + /** + * A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * + * @member {string|number} + */ get dropShadowColor() { return this._dropShadowColor; } - set dropShadowColor(dropShadowColor) + set dropShadowColor(dropShadowColor) // eslint-disable-line require-jsdoc { const outputColor = getColor(dropShadowColor); if (this._dropShadowColor !== outputColor) @@ -212,11 +249,16 @@ } } + /** + * Set a distance of the drop shadow + * + * @member {number} + */ get dropShadowDistance() { return this._dropShadowDistance; } - set dropShadowDistance(dropShadowDistance) + set dropShadowDistance(dropShadowDistance) // eslint-disable-line require-jsdoc { if (this._dropShadowDistance !== dropShadowDistance) { @@ -225,11 +267,18 @@ } } + /** + * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'. + * Can be an array to create a gradient eg ['#000000','#FFFFFF'] + * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} + * + * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern} + */ get fill() { return this._fill; } - set fill(fill) + set fill(fill) // eslint-disable-line require-jsdoc { const outputColor = getColor(fill); if (this._fill !== outputColor) @@ -239,11 +288,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient. + * See {@link PIXI.TEXT_GRADIENT} + * + * @member {number} + */ get fillGradientType() { return this._fillGradientType; } - set fillGradientType(fillGradientType) + set fillGradientType(fillGradientType) // eslint-disable-line require-jsdoc { if (this._fillGradientType !== fillGradientType) { @@ -252,11 +307,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this array can set the stop points + * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. + * + * @member {number[]} + */ get fillGradientStops() { return this._fillGradientStops; } - set fillGradientStops(fillGradientStops) + set fillGradientStops(fillGradientStops) // eslint-disable-line require-jsdoc { if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) { @@ -265,11 +326,16 @@ } } + /** + * The font family + * + * @member {string|string[]} + */ get fontFamily() { return this._fontFamily; } - set fontFamily(fontFamily) + set fontFamily(fontFamily) // eslint-disable-line require-jsdoc { if (this.fontFamily !== fontFamily) { @@ -278,11 +344,17 @@ } } + /** + * The font size + * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * + * @member {number|string} + */ get fontSize() { return this._fontSize; } - set fontSize(fontSize) + set fontSize(fontSize) // eslint-disable-line require-jsdoc { if (this._fontSize !== fontSize) { @@ -291,11 +363,17 @@ } } + /** + * The font style + * ('normal', 'italic' or 'oblique') + * + * @member {string} + */ get fontStyle() { return this._fontStyle; } - set fontStyle(fontStyle) + set fontStyle(fontStyle) // eslint-disable-line require-jsdoc { if (this._fontStyle !== fontStyle) { @@ -304,11 +382,17 @@ } } + /** + * The font variant + * ('normal' or 'small-caps') + * + * @member {string} + */ get fontVariant() { return this._fontVariant; } - set fontVariant(fontVariant) + set fontVariant(fontVariant) // eslint-disable-line require-jsdoc { if (this._fontVariant !== fontVariant) { @@ -317,11 +401,17 @@ } } + /** + * The font weight + * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') + * + * @member {string} + */ get fontWeight() { return this._fontWeight; } - set fontWeight(fontWeight) + set fontWeight(fontWeight) // eslint-disable-line require-jsdoc { if (this._fontWeight !== fontWeight) { @@ -330,11 +420,16 @@ } } + /** + * The amount of spacing between letters, default is 0 + * + * @member {number} + */ get letterSpacing() { return this._letterSpacing; } - set letterSpacing(letterSpacing) + set letterSpacing(letterSpacing) // eslint-disable-line require-jsdoc { if (this._letterSpacing !== letterSpacing) { @@ -343,11 +438,16 @@ } } + /** + * The line height, a number that represents the vertical space that a letter uses + * + * @member {number} + */ get lineHeight() { return this._lineHeight; } - set lineHeight(lineHeight) + set lineHeight(lineHeight) // eslint-disable-line require-jsdoc { if (this._lineHeight !== lineHeight) { @@ -356,11 +456,35 @@ } } + /** + * The space between lines + * + * @member {number} + */ + get leading() + { + return this._leading; + } + set leading(leading) // eslint-disable-line require-jsdoc + { + if (this._leading !== leading) + { + this._leading = leading; + this.styleID++; + } + } + + /** + * The lineJoin property sets the type of corner created, it can resolve spiked text issues. + * Default is 'miter' (creates a sharp corner). + * + * @member {string} + */ get lineJoin() { return this._lineJoin; } - set lineJoin(lineJoin) + set lineJoin(lineJoin) // eslint-disable-line require-jsdoc { if (this._lineJoin !== lineJoin) { @@ -369,11 +493,17 @@ } } + /** + * The miter limit to use when using the 'miter' lineJoin mode + * This can reduce or increase the spikiness of rendered text. + * + * @member {number} + */ get miterLimit() { return this._miterLimit; } - set miterLimit(miterLimit) + set miterLimit(miterLimit) // eslint-disable-line require-jsdoc { if (this._miterLimit !== miterLimit) { @@ -382,11 +512,17 @@ } } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * + * @member {number} + */ get padding() { return this._padding; } - set padding(padding) + set padding(padding) // eslint-disable-line require-jsdoc { if (this._padding !== padding) { @@ -395,11 +531,17 @@ } } + /** + * A canvas fillstyle that will be used on the text stroke + * e.g 'blue', '#FCFF00' + * + * @member {string|number} + */ get stroke() { return this._stroke; } - set stroke(stroke) + set stroke(stroke) // eslint-disable-line require-jsdoc { const outputColor = getColor(stroke); if (this._stroke !== outputColor) @@ -409,11 +551,17 @@ } } + /** + * A number that represents the thickness of the stroke. + * Default is 0 (no stroke) + * + * @member {number} + */ get strokeThickness() { return this._strokeThickness; } - set strokeThickness(strokeThickness) + set strokeThickness(strokeThickness) // eslint-disable-line require-jsdoc { if (this._strokeThickness !== strokeThickness) { @@ -422,11 +570,16 @@ } } + /** + * The baseline of the text that is rendered. + * + * @member {string} + */ get textBaseline() { return this._textBaseline; } - set textBaseline(textBaseline) + set textBaseline(textBaseline) // eslint-disable-line require-jsdoc { if (this._textBaseline !== textBaseline) { @@ -435,11 +588,16 @@ } } + /** + * Trim transparent borders + * + * @member {boolean} + */ get trim() { return this._trim; } - set trim(trim) + set trim(trim) // eslint-disable-line require-jsdoc { if (this._trim !== trim) { @@ -448,11 +606,16 @@ } } + /** + * Indicates if word wrap should be used + * + * @member {boolean} + */ get wordWrap() { return this._wordWrap; } - set wordWrap(wordWrap) + set wordWrap(wordWrap) // eslint-disable-line require-jsdoc { if (this._wordWrap !== wordWrap) { @@ -461,11 +624,16 @@ } } + /** + * The width at which text will wrap, it needs wordWrap to be set to true + * + * @member {number} + */ get wordWrapWidth() { return this._wordWrapWidth; } - set wordWrapWidth(wordWrapWidth) + set wordWrapWidth(wordWrapWidth) // eslint-disable-line require-jsdoc { if (this._wordWrapWidth !== wordWrapWidth) { diff --git a/src/core/textures/Texture.js b/src/core/textures/Texture.js index 3922e52..3a472be 100644 --- a/src/core/textures/Texture.js +++ b/src/core/textures/Texture.js @@ -521,7 +521,11 @@ { for (let i = 0; i < texture.textureCacheIds.length; ++i) { - delete TextureCache[texture.textureCacheIds[i]]; + // Check that texture matches the one being passed in before deleting it from the cache. + if (TextureCache[texture.textureCacheIds[i]] === texture) + { + delete TextureCache[texture.textureCacheIds[i]]; + } } texture.textureCacheIds.length = 0; diff --git a/src/core/ticker/Ticker.js b/src/core/ticker/Ticker.js index 1d58724..e07e0a6 100644 --- a/src/core/ticker/Ticker.js +++ b/src/core/ticker/Ticker.js @@ -81,9 +81,9 @@ * this value will have a precision of 1 µs. * * @member {number} - * @default 0 + * @default -1 */ - this.lastTime = 0; + this.lastTime = -1; /** * Factor of current {@link PIXI.ticker.Ticker#deltaTime}. diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 5354e2c..6eaf2e0 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -244,6 +244,7 @@ ); context.restore(); + this.renderer.invalidateBlendMode(); } /** diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 71f31e2..c682a36 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -32,6 +32,7 @@ trim: false, wordWrap: false, wordWrapWidth: 100, + leading: 0, }; /** @@ -53,7 +54,7 @@ * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius - * @param {string} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient @@ -70,6 +71,7 @@ * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps') * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', * '200', '300', '400', '500', '600', '700', 800' or '900') + * @param {number} [style.leading=0] - The space between lines * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0 * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve @@ -120,11 +122,16 @@ Object.assign(this, defaultStyle); } + /** + * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text + * + * @member {string} + */ get align() { return this._align; } - set align(align) + set align(align) // eslint-disable-line require-jsdoc { if (this._align !== align) { @@ -133,11 +140,16 @@ } } + /** + * Indicates if lines can be wrapped within words, it needs wordWrap to be set to true + * + * @member {boolean} + */ get breakWords() { return this._breakWords; } - set breakWords(breakWords) + set breakWords(breakWords) // eslint-disable-line require-jsdoc { if (this._breakWords !== breakWords) { @@ -146,11 +158,16 @@ } } + /** + * Set a drop shadow for the text + * + * @member {boolean} + */ get dropShadow() { return this._dropShadow; } - set dropShadow(dropShadow) + set dropShadow(dropShadow) // eslint-disable-line require-jsdoc { if (this._dropShadow !== dropShadow) { @@ -159,11 +176,16 @@ } } + /** + * Set alpha for the drop shadow + * + * @member {number} + */ get dropShadowAlpha() { return this._dropShadowAlpha; } - set dropShadowAlpha(dropShadowAlpha) + set dropShadowAlpha(dropShadowAlpha) // eslint-disable-line require-jsdoc { if (this._dropShadowAlpha !== dropShadowAlpha) { @@ -172,11 +194,16 @@ } } + /** + * Set a angle of the drop shadow + * + * @member {number} + */ get dropShadowAngle() { return this._dropShadowAngle; } - set dropShadowAngle(dropShadowAngle) + set dropShadowAngle(dropShadowAngle) // eslint-disable-line require-jsdoc { if (this._dropShadowAngle !== dropShadowAngle) { @@ -185,11 +212,16 @@ } } + /** + * Set a shadow blur radius + * + * @member {number} + */ get dropShadowBlur() { return this._dropShadowBlur; } - set dropShadowBlur(dropShadowBlur) + set dropShadowBlur(dropShadowBlur) // eslint-disable-line require-jsdoc { if (this._dropShadowBlur !== dropShadowBlur) { @@ -198,11 +230,16 @@ } } + /** + * A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * + * @member {string|number} + */ get dropShadowColor() { return this._dropShadowColor; } - set dropShadowColor(dropShadowColor) + set dropShadowColor(dropShadowColor) // eslint-disable-line require-jsdoc { const outputColor = getColor(dropShadowColor); if (this._dropShadowColor !== outputColor) @@ -212,11 +249,16 @@ } } + /** + * Set a distance of the drop shadow + * + * @member {number} + */ get dropShadowDistance() { return this._dropShadowDistance; } - set dropShadowDistance(dropShadowDistance) + set dropShadowDistance(dropShadowDistance) // eslint-disable-line require-jsdoc { if (this._dropShadowDistance !== dropShadowDistance) { @@ -225,11 +267,18 @@ } } + /** + * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'. + * Can be an array to create a gradient eg ['#000000','#FFFFFF'] + * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} + * + * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern} + */ get fill() { return this._fill; } - set fill(fill) + set fill(fill) // eslint-disable-line require-jsdoc { const outputColor = getColor(fill); if (this._fill !== outputColor) @@ -239,11 +288,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient. + * See {@link PIXI.TEXT_GRADIENT} + * + * @member {number} + */ get fillGradientType() { return this._fillGradientType; } - set fillGradientType(fillGradientType) + set fillGradientType(fillGradientType) // eslint-disable-line require-jsdoc { if (this._fillGradientType !== fillGradientType) { @@ -252,11 +307,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this array can set the stop points + * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. + * + * @member {number[]} + */ get fillGradientStops() { return this._fillGradientStops; } - set fillGradientStops(fillGradientStops) + set fillGradientStops(fillGradientStops) // eslint-disable-line require-jsdoc { if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) { @@ -265,11 +326,16 @@ } } + /** + * The font family + * + * @member {string|string[]} + */ get fontFamily() { return this._fontFamily; } - set fontFamily(fontFamily) + set fontFamily(fontFamily) // eslint-disable-line require-jsdoc { if (this.fontFamily !== fontFamily) { @@ -278,11 +344,17 @@ } } + /** + * The font size + * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * + * @member {number|string} + */ get fontSize() { return this._fontSize; } - set fontSize(fontSize) + set fontSize(fontSize) // eslint-disable-line require-jsdoc { if (this._fontSize !== fontSize) { @@ -291,11 +363,17 @@ } } + /** + * The font style + * ('normal', 'italic' or 'oblique') + * + * @member {string} + */ get fontStyle() { return this._fontStyle; } - set fontStyle(fontStyle) + set fontStyle(fontStyle) // eslint-disable-line require-jsdoc { if (this._fontStyle !== fontStyle) { @@ -304,11 +382,17 @@ } } + /** + * The font variant + * ('normal' or 'small-caps') + * + * @member {string} + */ get fontVariant() { return this._fontVariant; } - set fontVariant(fontVariant) + set fontVariant(fontVariant) // eslint-disable-line require-jsdoc { if (this._fontVariant !== fontVariant) { @@ -317,11 +401,17 @@ } } + /** + * The font weight + * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') + * + * @member {string} + */ get fontWeight() { return this._fontWeight; } - set fontWeight(fontWeight) + set fontWeight(fontWeight) // eslint-disable-line require-jsdoc { if (this._fontWeight !== fontWeight) { @@ -330,11 +420,16 @@ } } + /** + * The amount of spacing between letters, default is 0 + * + * @member {number} + */ get letterSpacing() { return this._letterSpacing; } - set letterSpacing(letterSpacing) + set letterSpacing(letterSpacing) // eslint-disable-line require-jsdoc { if (this._letterSpacing !== letterSpacing) { @@ -343,11 +438,16 @@ } } + /** + * The line height, a number that represents the vertical space that a letter uses + * + * @member {number} + */ get lineHeight() { return this._lineHeight; } - set lineHeight(lineHeight) + set lineHeight(lineHeight) // eslint-disable-line require-jsdoc { if (this._lineHeight !== lineHeight) { @@ -356,11 +456,35 @@ } } + /** + * The space between lines + * + * @member {number} + */ + get leading() + { + return this._leading; + } + set leading(leading) // eslint-disable-line require-jsdoc + { + if (this._leading !== leading) + { + this._leading = leading; + this.styleID++; + } + } + + /** + * The lineJoin property sets the type of corner created, it can resolve spiked text issues. + * Default is 'miter' (creates a sharp corner). + * + * @member {string} + */ get lineJoin() { return this._lineJoin; } - set lineJoin(lineJoin) + set lineJoin(lineJoin) // eslint-disable-line require-jsdoc { if (this._lineJoin !== lineJoin) { @@ -369,11 +493,17 @@ } } + /** + * The miter limit to use when using the 'miter' lineJoin mode + * This can reduce or increase the spikiness of rendered text. + * + * @member {number} + */ get miterLimit() { return this._miterLimit; } - set miterLimit(miterLimit) + set miterLimit(miterLimit) // eslint-disable-line require-jsdoc { if (this._miterLimit !== miterLimit) { @@ -382,11 +512,17 @@ } } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * + * @member {number} + */ get padding() { return this._padding; } - set padding(padding) + set padding(padding) // eslint-disable-line require-jsdoc { if (this._padding !== padding) { @@ -395,11 +531,17 @@ } } + /** + * A canvas fillstyle that will be used on the text stroke + * e.g 'blue', '#FCFF00' + * + * @member {string|number} + */ get stroke() { return this._stroke; } - set stroke(stroke) + set stroke(stroke) // eslint-disable-line require-jsdoc { const outputColor = getColor(stroke); if (this._stroke !== outputColor) @@ -409,11 +551,17 @@ } } + /** + * A number that represents the thickness of the stroke. + * Default is 0 (no stroke) + * + * @member {number} + */ get strokeThickness() { return this._strokeThickness; } - set strokeThickness(strokeThickness) + set strokeThickness(strokeThickness) // eslint-disable-line require-jsdoc { if (this._strokeThickness !== strokeThickness) { @@ -422,11 +570,16 @@ } } + /** + * The baseline of the text that is rendered. + * + * @member {string} + */ get textBaseline() { return this._textBaseline; } - set textBaseline(textBaseline) + set textBaseline(textBaseline) // eslint-disable-line require-jsdoc { if (this._textBaseline !== textBaseline) { @@ -435,11 +588,16 @@ } } + /** + * Trim transparent borders + * + * @member {boolean} + */ get trim() { return this._trim; } - set trim(trim) + set trim(trim) // eslint-disable-line require-jsdoc { if (this._trim !== trim) { @@ -448,11 +606,16 @@ } } + /** + * Indicates if word wrap should be used + * + * @member {boolean} + */ get wordWrap() { return this._wordWrap; } - set wordWrap(wordWrap) + set wordWrap(wordWrap) // eslint-disable-line require-jsdoc { if (this._wordWrap !== wordWrap) { @@ -461,11 +624,16 @@ } } + /** + * The width at which text will wrap, it needs wordWrap to be set to true + * + * @member {number} + */ get wordWrapWidth() { return this._wordWrapWidth; } - set wordWrapWidth(wordWrapWidth) + set wordWrapWidth(wordWrapWidth) // eslint-disable-line require-jsdoc { if (this._wordWrapWidth !== wordWrapWidth) { diff --git a/src/core/textures/Texture.js b/src/core/textures/Texture.js index 3922e52..3a472be 100644 --- a/src/core/textures/Texture.js +++ b/src/core/textures/Texture.js @@ -521,7 +521,11 @@ { for (let i = 0; i < texture.textureCacheIds.length; ++i) { - delete TextureCache[texture.textureCacheIds[i]]; + // Check that texture matches the one being passed in before deleting it from the cache. + if (TextureCache[texture.textureCacheIds[i]] === texture) + { + delete TextureCache[texture.textureCacheIds[i]]; + } } texture.textureCacheIds.length = 0; diff --git a/src/core/ticker/Ticker.js b/src/core/ticker/Ticker.js index 1d58724..e07e0a6 100644 --- a/src/core/ticker/Ticker.js +++ b/src/core/ticker/Ticker.js @@ -81,9 +81,9 @@ * this value will have a precision of 1 µs. * * @member {number} - * @default 0 + * @default -1 */ - this.lastTime = 0; + this.lastTime = -1; /** * Factor of current {@link PIXI.ticker.Ticker#deltaTime}. diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 5354e2c..6eaf2e0 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -244,6 +244,7 @@ ); context.restore(); + this.renderer.invalidateBlendMode(); } /** diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 2196fb0..1c725d2 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -248,12 +248,7 @@ let finalWidth = 0; let finalHeight = 0; - const compositeOperation = renderer.blendModes[this.blendMode]; - - if (compositeOperation !== context.globalCompositeOperation) - { - context.globalCompositeOperation = compositeOperation; - } + renderer.setBlendMode(this.blendMode); context.globalAlpha = this.worldAlpha; diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 71f31e2..c682a36 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -32,6 +32,7 @@ trim: false, wordWrap: false, wordWrapWidth: 100, + leading: 0, }; /** @@ -53,7 +54,7 @@ * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius - * @param {string} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient @@ -70,6 +71,7 @@ * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps') * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', * '200', '300', '400', '500', '600', '700', 800' or '900') + * @param {number} [style.leading=0] - The space between lines * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0 * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve @@ -120,11 +122,16 @@ Object.assign(this, defaultStyle); } + /** + * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text + * + * @member {string} + */ get align() { return this._align; } - set align(align) + set align(align) // eslint-disable-line require-jsdoc { if (this._align !== align) { @@ -133,11 +140,16 @@ } } + /** + * Indicates if lines can be wrapped within words, it needs wordWrap to be set to true + * + * @member {boolean} + */ get breakWords() { return this._breakWords; } - set breakWords(breakWords) + set breakWords(breakWords) // eslint-disable-line require-jsdoc { if (this._breakWords !== breakWords) { @@ -146,11 +158,16 @@ } } + /** + * Set a drop shadow for the text + * + * @member {boolean} + */ get dropShadow() { return this._dropShadow; } - set dropShadow(dropShadow) + set dropShadow(dropShadow) // eslint-disable-line require-jsdoc { if (this._dropShadow !== dropShadow) { @@ -159,11 +176,16 @@ } } + /** + * Set alpha for the drop shadow + * + * @member {number} + */ get dropShadowAlpha() { return this._dropShadowAlpha; } - set dropShadowAlpha(dropShadowAlpha) + set dropShadowAlpha(dropShadowAlpha) // eslint-disable-line require-jsdoc { if (this._dropShadowAlpha !== dropShadowAlpha) { @@ -172,11 +194,16 @@ } } + /** + * Set a angle of the drop shadow + * + * @member {number} + */ get dropShadowAngle() { return this._dropShadowAngle; } - set dropShadowAngle(dropShadowAngle) + set dropShadowAngle(dropShadowAngle) // eslint-disable-line require-jsdoc { if (this._dropShadowAngle !== dropShadowAngle) { @@ -185,11 +212,16 @@ } } + /** + * Set a shadow blur radius + * + * @member {number} + */ get dropShadowBlur() { return this._dropShadowBlur; } - set dropShadowBlur(dropShadowBlur) + set dropShadowBlur(dropShadowBlur) // eslint-disable-line require-jsdoc { if (this._dropShadowBlur !== dropShadowBlur) { @@ -198,11 +230,16 @@ } } + /** + * A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * + * @member {string|number} + */ get dropShadowColor() { return this._dropShadowColor; } - set dropShadowColor(dropShadowColor) + set dropShadowColor(dropShadowColor) // eslint-disable-line require-jsdoc { const outputColor = getColor(dropShadowColor); if (this._dropShadowColor !== outputColor) @@ -212,11 +249,16 @@ } } + /** + * Set a distance of the drop shadow + * + * @member {number} + */ get dropShadowDistance() { return this._dropShadowDistance; } - set dropShadowDistance(dropShadowDistance) + set dropShadowDistance(dropShadowDistance) // eslint-disable-line require-jsdoc { if (this._dropShadowDistance !== dropShadowDistance) { @@ -225,11 +267,18 @@ } } + /** + * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'. + * Can be an array to create a gradient eg ['#000000','#FFFFFF'] + * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} + * + * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern} + */ get fill() { return this._fill; } - set fill(fill) + set fill(fill) // eslint-disable-line require-jsdoc { const outputColor = getColor(fill); if (this._fill !== outputColor) @@ -239,11 +288,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient. + * See {@link PIXI.TEXT_GRADIENT} + * + * @member {number} + */ get fillGradientType() { return this._fillGradientType; } - set fillGradientType(fillGradientType) + set fillGradientType(fillGradientType) // eslint-disable-line require-jsdoc { if (this._fillGradientType !== fillGradientType) { @@ -252,11 +307,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this array can set the stop points + * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. + * + * @member {number[]} + */ get fillGradientStops() { return this._fillGradientStops; } - set fillGradientStops(fillGradientStops) + set fillGradientStops(fillGradientStops) // eslint-disable-line require-jsdoc { if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) { @@ -265,11 +326,16 @@ } } + /** + * The font family + * + * @member {string|string[]} + */ get fontFamily() { return this._fontFamily; } - set fontFamily(fontFamily) + set fontFamily(fontFamily) // eslint-disable-line require-jsdoc { if (this.fontFamily !== fontFamily) { @@ -278,11 +344,17 @@ } } + /** + * The font size + * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * + * @member {number|string} + */ get fontSize() { return this._fontSize; } - set fontSize(fontSize) + set fontSize(fontSize) // eslint-disable-line require-jsdoc { if (this._fontSize !== fontSize) { @@ -291,11 +363,17 @@ } } + /** + * The font style + * ('normal', 'italic' or 'oblique') + * + * @member {string} + */ get fontStyle() { return this._fontStyle; } - set fontStyle(fontStyle) + set fontStyle(fontStyle) // eslint-disable-line require-jsdoc { if (this._fontStyle !== fontStyle) { @@ -304,11 +382,17 @@ } } + /** + * The font variant + * ('normal' or 'small-caps') + * + * @member {string} + */ get fontVariant() { return this._fontVariant; } - set fontVariant(fontVariant) + set fontVariant(fontVariant) // eslint-disable-line require-jsdoc { if (this._fontVariant !== fontVariant) { @@ -317,11 +401,17 @@ } } + /** + * The font weight + * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') + * + * @member {string} + */ get fontWeight() { return this._fontWeight; } - set fontWeight(fontWeight) + set fontWeight(fontWeight) // eslint-disable-line require-jsdoc { if (this._fontWeight !== fontWeight) { @@ -330,11 +420,16 @@ } } + /** + * The amount of spacing between letters, default is 0 + * + * @member {number} + */ get letterSpacing() { return this._letterSpacing; } - set letterSpacing(letterSpacing) + set letterSpacing(letterSpacing) // eslint-disable-line require-jsdoc { if (this._letterSpacing !== letterSpacing) { @@ -343,11 +438,16 @@ } } + /** + * The line height, a number that represents the vertical space that a letter uses + * + * @member {number} + */ get lineHeight() { return this._lineHeight; } - set lineHeight(lineHeight) + set lineHeight(lineHeight) // eslint-disable-line require-jsdoc { if (this._lineHeight !== lineHeight) { @@ -356,11 +456,35 @@ } } + /** + * The space between lines + * + * @member {number} + */ + get leading() + { + return this._leading; + } + set leading(leading) // eslint-disable-line require-jsdoc + { + if (this._leading !== leading) + { + this._leading = leading; + this.styleID++; + } + } + + /** + * The lineJoin property sets the type of corner created, it can resolve spiked text issues. + * Default is 'miter' (creates a sharp corner). + * + * @member {string} + */ get lineJoin() { return this._lineJoin; } - set lineJoin(lineJoin) + set lineJoin(lineJoin) // eslint-disable-line require-jsdoc { if (this._lineJoin !== lineJoin) { @@ -369,11 +493,17 @@ } } + /** + * The miter limit to use when using the 'miter' lineJoin mode + * This can reduce or increase the spikiness of rendered text. + * + * @member {number} + */ get miterLimit() { return this._miterLimit; } - set miterLimit(miterLimit) + set miterLimit(miterLimit) // eslint-disable-line require-jsdoc { if (this._miterLimit !== miterLimit) { @@ -382,11 +512,17 @@ } } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * + * @member {number} + */ get padding() { return this._padding; } - set padding(padding) + set padding(padding) // eslint-disable-line require-jsdoc { if (this._padding !== padding) { @@ -395,11 +531,17 @@ } } + /** + * A canvas fillstyle that will be used on the text stroke + * e.g 'blue', '#FCFF00' + * + * @member {string|number} + */ get stroke() { return this._stroke; } - set stroke(stroke) + set stroke(stroke) // eslint-disable-line require-jsdoc { const outputColor = getColor(stroke); if (this._stroke !== outputColor) @@ -409,11 +551,17 @@ } } + /** + * A number that represents the thickness of the stroke. + * Default is 0 (no stroke) + * + * @member {number} + */ get strokeThickness() { return this._strokeThickness; } - set strokeThickness(strokeThickness) + set strokeThickness(strokeThickness) // eslint-disable-line require-jsdoc { if (this._strokeThickness !== strokeThickness) { @@ -422,11 +570,16 @@ } } + /** + * The baseline of the text that is rendered. + * + * @member {string} + */ get textBaseline() { return this._textBaseline; } - set textBaseline(textBaseline) + set textBaseline(textBaseline) // eslint-disable-line require-jsdoc { if (this._textBaseline !== textBaseline) { @@ -435,11 +588,16 @@ } } + /** + * Trim transparent borders + * + * @member {boolean} + */ get trim() { return this._trim; } - set trim(trim) + set trim(trim) // eslint-disable-line require-jsdoc { if (this._trim !== trim) { @@ -448,11 +606,16 @@ } } + /** + * Indicates if word wrap should be used + * + * @member {boolean} + */ get wordWrap() { return this._wordWrap; } - set wordWrap(wordWrap) + set wordWrap(wordWrap) // eslint-disable-line require-jsdoc { if (this._wordWrap !== wordWrap) { @@ -461,11 +624,16 @@ } } + /** + * The width at which text will wrap, it needs wordWrap to be set to true + * + * @member {number} + */ get wordWrapWidth() { return this._wordWrapWidth; } - set wordWrapWidth(wordWrapWidth) + set wordWrapWidth(wordWrapWidth) // eslint-disable-line require-jsdoc { if (this._wordWrapWidth !== wordWrapWidth) { diff --git a/src/core/textures/Texture.js b/src/core/textures/Texture.js index 3922e52..3a472be 100644 --- a/src/core/textures/Texture.js +++ b/src/core/textures/Texture.js @@ -521,7 +521,11 @@ { for (let i = 0; i < texture.textureCacheIds.length; ++i) { - delete TextureCache[texture.textureCacheIds[i]]; + // Check that texture matches the one being passed in before deleting it from the cache. + if (TextureCache[texture.textureCacheIds[i]] === texture) + { + delete TextureCache[texture.textureCacheIds[i]]; + } } texture.textureCacheIds.length = 0; diff --git a/src/core/ticker/Ticker.js b/src/core/ticker/Ticker.js index 1d58724..e07e0a6 100644 --- a/src/core/ticker/Ticker.js +++ b/src/core/ticker/Ticker.js @@ -81,9 +81,9 @@ * this value will have a precision of 1 µs. * * @member {number} - * @default 0 + * @default -1 */ - this.lastTime = 0; + this.lastTime = -1; /** * Factor of current {@link PIXI.ticker.Ticker#deltaTime}. diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 5354e2c..6eaf2e0 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -244,6 +244,7 @@ ); context.restore(); + this.renderer.invalidateBlendMode(); } /** diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 2196fb0..1c725d2 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -248,12 +248,7 @@ let finalWidth = 0; let finalHeight = 0; - const compositeOperation = renderer.blendModes[this.blendMode]; - - if (compositeOperation !== context.globalCompositeOperation) - { - context.globalCompositeOperation = compositeOperation; - } + renderer.setBlendMode(this.blendMode); context.globalAlpha = this.worldAlpha; diff --git a/test/core/Application.js b/test/core/Application.js index 00eb286..6d89c36 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -34,4 +34,18 @@ done(); }); }); + + it('should not start application before calling start method if options.autoStart is false', function (done) + { + const app = new PIXI.Application({ autoStart: false }); + + expect(app.ticker.started).to.be.false; + app.start(); + + app.ticker.addOnce(() => + { + app.destroy(); + done(); + }); + }); }); diff --git a/LICENSE b/LICENSE index d2dcf81..d9de993 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2013-2016 Mathew Groves, Chad Engler +Copyright (c) 2013-2017 Mathew Groves, Chad Engler Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 80d2352..00d8e3b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,9 @@ -PixiJS — A 2D JavaScript Renderer +PixiJS — The HTML5 Creation Engine ============= ![pixi.js logo](http://www.goodboydigital.com/pixijs/pixiV4_wide_full.jpg) - - - -[![Inline docs](http://inch-ci.org/github/GoodBoyDigital/pixi.js.svg?branch=dev)](http://inch-ci.org/github/GoodBoyDigital/pixi.js) +[![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) The aim of this project is to provide a fast lightweight 2D library that works @@ -15,7 +12,7 @@ If you want to keep up to date with the latest PixiJS news then feel free to follow us on twitter ([@doormat23](https://twitter.com/doormat23), [@rolnaaba](https://twitter.com/rolnaaba), [@bigtimebuddy](https://twitter.com/bigtimebuddy), [@ivanpopelyshev](https://twitter.com/ivanpopelyshev)) -and we will keep you posted! You can also check back on [our site](http://www.goodboydigital.com/blog) +and we will keep you posted! You can also check back on [our site](http://www.pixijs.com) as any breakthroughs will be posted up there too! **Your support helps us make PixiJS even better. Make your pledge on [Patreon](https://www.patreon.com/user?u=2384552&ty=h&u=2384552) and we'll love you forever!** @@ -33,7 +30,7 @@ - Getting started: Check out @kittykatattack's comprehensive [tutorial](https://github.com/kittykatattack/learningPixi). - Examples: Get stuck right in and play around with PixiJS code and features right [here](http://pixijs.github.io/examples/)! - Docs: Get to know the PixiJS API by checking out the [docs](https://pixijs.github.io/docs/). -- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki/Resources). +- Wiki: Other misc tutorials and resources are [on the Wiki](https://github.com/pixijs/pixi.js/wiki). ### Community ### - Forums: Check out the [forum](http://www.html5gamedevs.com/forum/15-pixijs/) and [Stackoverflow](http://stackoverflow.com/search?q=pixi.js), both friendly places to ask your pixi questions. @@ -65,7 +62,7 @@ ### Demos ### -- [WebGL Filters!](http://www.goodboydigital.com/pixijs/examples/15/indexAll.html) +- [WebGL Filters!](http://pixijs.github.io/pixi-filters/examples/) - [Run pixie run](http://www.goodboydigital.com/runpixierun) - [Fight for Everyone](http://www.goodboydigital.com/casestudies/fightforeveryone) - [Flash vs HTML](http://flashvhtml.com) @@ -108,7 +105,7 @@ - Primitive Drawing - Masking - Filters -- [User Plugins](https://github.com/pixijs/pixi.js/wiki/Pixi-v3-Plugins) +- [User Plugins](https://github.com/pixijs/pixi.js/wiki/v3-Pixi-Plugins) ### Basic Usage Example ### diff --git a/package.json b/package.json index cf34ec1..b5233fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pixi.js", "version": "4.5.4", - "description": "PixiJS is a fast lightweight 2D library that works across all devices.", + "description": "The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.", "author": "Mat Groves", "contributors": [ "Ivan Popelyshev ", @@ -77,7 +77,7 @@ "floss": "^2.0.1", "jaguarjs-jsdoc": "^1.0.1", "js-md5": "^0.4.1", - "jsdoc": "^3.4.2", + "jsdoc": "3.4.3", "minimist": "^1.2.0", "mkdirp": "^0.5.1", "parallelshell": "^2.0.0", diff --git a/scripts/jsdoc.conf.json b/scripts/jsdoc.conf.json index a743809..8a3afee 100644 --- a/scripts/jsdoc.conf.json +++ b/scripts/jsdoc.conf.json @@ -24,9 +24,9 @@ }, "applicationName": "PixiJS", "footer" : "Made with ♥ by Goodboy Digital (goodboydigital.com)", - "copyright" : "PixiJS Copyright © 2013-2016 Mat Groves.", + "copyright" : "PixiJS Copyright © 2013-2017 Mat Groves.", "disqus": "", - "googleAnalytics": "", + "googleAnalytics": "UA-103772589-5", "openGraph": { "title": "", "type": "website", diff --git a/src/core/Application.js b/src/core/Application.js index 7248ff0..c48104a 100644 --- a/src/core/Application.js +++ b/src/core/Application.js @@ -27,6 +27,9 @@ // eslint-disable-next-line valid-jsdoc /** * @param {object} [options] - The optional renderer parameters + * @param {boolean} [options.autoStart=true] - automatically starts the rendering after the construction. + * Note that setting this parameter to false does NOT stop the shared ticker even if you set + * options.sharedTicker to true in case that it is already started. Stop it by your own. * @param {number} [options.width=800] - the width of the renderers view * @param {number} [options.height=600] - the height of the renderers view * @param {HTMLCanvasElement} [options.view] - the canvas to use as a view, optional @@ -46,6 +49,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @param {boolean} [options.sharedTicker=false] - `true` to use PIXI.ticker.shared, `false` to create new ticker. * @param {boolean} [options.sharedLoader=false] - `true` to use PIXI.loaders.shared, `false` to create new Loader. */ @@ -68,6 +73,7 @@ * @protected */ this._options = options = Object.assign({ + autoStart: true, sharedTicker: false, forceCanvas: false, sharedLoader: false, @@ -100,7 +106,10 @@ this.ticker = options.sharedTicker ? shared : new Ticker(); // Start the rendering - this.start(); + if (options.autoStart) + { + this.start(); + } } set ticker(ticker) // eslint-disable-line require-jsdoc diff --git a/src/core/autoDetectRenderer.js b/src/core/autoDetectRenderer.js index 486d90b..7fd1c3e 100644 --- a/src/core/autoDetectRenderer.js +++ b/src/core/autoDetectRenderer.js @@ -30,6 +30,8 @@ * FXAA is faster, but may not always look as great **webgl only** * @param {boolean} [options.legacy=false] - `true` to ensure compatibility with older / less advanced devices. * If you experience unexplained flickering try setting this to true. **webgl only** + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card **webgl only** * @return {PIXI.WebGLRenderer|PIXI.CanvasRenderer} Returns WebGL renderer if available, otherwise CanvasRenderer */ export function autoDetectRenderer(options, arg1, arg2, arg3) diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index 119103a..4dcd773 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -201,6 +201,7 @@ context.setTransform(1, 0, 0, 1, 0, 0); context.globalAlpha = 1; + this._activeBlendMode = BLEND_MODES.NORMAL; context.globalCompositeOperation = this.blendModes[BLEND_MODES.NORMAL]; if (navigator.isCocoonJS && this.view.screencanvas) @@ -318,6 +319,14 @@ this.rootContext[this.smoothProperty] = (settings.SCALE_MODE === SCALE_MODES.LINEAR); } } + + /** + * Checks if blend mode has changed. + */ + invalidateBlendMode() + { + this._activeBlendMode = this.blendModes.indexOf(this.context.globalCompositeOperation); + } } /** diff --git a/src/core/renderers/canvas/utils/CanvasMaskManager.js b/src/core/renderers/canvas/utils/CanvasMaskManager.js index 169e268..e3e52d4 100644 --- a/src/core/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/core/renderers/canvas/utils/CanvasMaskManager.js @@ -160,6 +160,7 @@ popMask(renderer) { renderer.context.restore(); + renderer.invalidateBlendMode(); } /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 9f8e97e..f2d1c12 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -53,7 +53,9 @@ * @param {number} [options.backgroundColor=0x000000] - The background color of the rendered area * (shown if not transparent). * @param {boolean} [options.legacy=false] - If true PixiJS will aim to ensure compatibility - * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * with older / less advanced devices. If you experiance unexplained flickering try setting this to true. + * @param {string} [options.powerPreference] - Parameter passed to webgl context, set to "high-performance" + * for devices with dual graphics card */ constructor(options, arg2, arg3) { @@ -92,6 +94,7 @@ premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', stencil: true, preserveDrawingBuffer: this.options.preserveDrawingBuffer, + powerPreference: this.options.powerPreference, }; this._backgroundColorRgba[3] = this.transparent ? 0 : 1; diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */ diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 4f9ae43..0aeda37 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -357,7 +357,7 @@ this._bounds.minX = this._texture.orig.width * -this._anchor._x; this._bounds.minY = this._texture.orig.height * -this._anchor._y; this._bounds.maxX = this._texture.orig.width * (1 - this._anchor._x); - this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._x); + this._bounds.maxY = this._texture.orig.height * (1 - this._anchor._y); if (!rect) { diff --git a/src/core/sprites/canvas/CanvasTinter.js b/src/core/sprites/canvas/CanvasTinter.js index af018d4..9415d31 100644 --- a/src/core/sprites/canvas/CanvasTinter.js +++ b/src/core/sprites/canvas/CanvasTinter.js @@ -89,6 +89,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -120,6 +121,7 @@ crop.width, crop.height ); + context.restore(); }, /** @@ -144,6 +146,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.fillStyle = `#${(`00000${(color | 0).toString(16)}`).substr(-6)}`; context.fillRect(0, 0, crop.width, crop.height); @@ -162,6 +165,7 @@ ); // context.globalCompositeOperation = 'copy'; + context.restore(); }, /** @@ -186,6 +190,7 @@ canvas.width = Math.ceil(crop.width); canvas.height = Math.ceil(crop.height); + context.save(); context.globalCompositeOperation = 'copy'; context.drawImage( texture.baseTexture.source, @@ -198,6 +203,7 @@ crop.width, crop.height ); + context.restore(); const rgbValues = hex2rgb(color); const r = rgbValues[0]; diff --git a/src/core/text/TextMetrics.js b/src/core/text/TextMetrics.js index 27bd145..c4f32e1 100644 --- a/src/core/text/TextMetrics.js +++ b/src/core/text/TextMetrics.js @@ -69,7 +69,7 @@ const lineHeight = style.lineHeight || fontProperties.fontSize + style.strokeThickness; let height = Math.max(lineHeight, fontProperties.fontSize + style.strokeThickness) - + ((lines.length - 1) * lineHeight); + + ((lines.length - 1) * (lineHeight + style.leading)); if (style.dropShadow) { @@ -83,7 +83,7 @@ height, lines, lineWidths, - lineHeight, + lineHeight + style.leading, maxLineWidth, fontProperties ); diff --git a/src/core/text/TextStyle.js b/src/core/text/TextStyle.js index 71f31e2..c682a36 100644 --- a/src/core/text/TextStyle.js +++ b/src/core/text/TextStyle.js @@ -32,6 +32,7 @@ trim: false, wordWrap: false, wordWrapWidth: 100, + leading: 0, }; /** @@ -53,7 +54,7 @@ * @param {number} [style.dropShadowAlpha=1] - Set alpha for the drop shadow * @param {number} [style.dropShadowAngle=Math.PI/6] - Set a angle of the drop shadow * @param {number} [style.dropShadowBlur=0] - Set a shadow blur radius - * @param {string} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * @param {string|number} [style.dropShadowColor='black'] - A fill style to be used on the dropshadow e.g 'red', '#00FF00' * @param {number} [style.dropShadowDistance=5] - Set a distance of the drop shadow * @param {string|string[]|number|number[]|CanvasGradient|CanvasPattern} [style.fill='black'] - A canvas * fillstyle that will be used on the text e.g 'red', '#00FF00'. Can be an array to create a gradient @@ -70,6 +71,7 @@ * @param {string} [style.fontVariant='normal'] - The font variant ('normal' or 'small-caps') * @param {string} [style.fontWeight='normal'] - The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', * '200', '300', '400', '500', '600', '700', 800' or '900') + * @param {number} [style.leading=0] - The space between lines * @param {number} [style.letterSpacing=0] - The amount of spacing between letters, default is 0 * @param {number} [style.lineHeight] - The line height, a number that represents the vertical space that a letter uses * @param {string} [style.lineJoin='miter'] - The lineJoin property sets the type of corner created, it can resolve @@ -120,11 +122,16 @@ Object.assign(this, defaultStyle); } + /** + * Alignment for multiline text ('left', 'center' or 'right'), does not affect single line text + * + * @member {string} + */ get align() { return this._align; } - set align(align) + set align(align) // eslint-disable-line require-jsdoc { if (this._align !== align) { @@ -133,11 +140,16 @@ } } + /** + * Indicates if lines can be wrapped within words, it needs wordWrap to be set to true + * + * @member {boolean} + */ get breakWords() { return this._breakWords; } - set breakWords(breakWords) + set breakWords(breakWords) // eslint-disable-line require-jsdoc { if (this._breakWords !== breakWords) { @@ -146,11 +158,16 @@ } } + /** + * Set a drop shadow for the text + * + * @member {boolean} + */ get dropShadow() { return this._dropShadow; } - set dropShadow(dropShadow) + set dropShadow(dropShadow) // eslint-disable-line require-jsdoc { if (this._dropShadow !== dropShadow) { @@ -159,11 +176,16 @@ } } + /** + * Set alpha for the drop shadow + * + * @member {number} + */ get dropShadowAlpha() { return this._dropShadowAlpha; } - set dropShadowAlpha(dropShadowAlpha) + set dropShadowAlpha(dropShadowAlpha) // eslint-disable-line require-jsdoc { if (this._dropShadowAlpha !== dropShadowAlpha) { @@ -172,11 +194,16 @@ } } + /** + * Set a angle of the drop shadow + * + * @member {number} + */ get dropShadowAngle() { return this._dropShadowAngle; } - set dropShadowAngle(dropShadowAngle) + set dropShadowAngle(dropShadowAngle) // eslint-disable-line require-jsdoc { if (this._dropShadowAngle !== dropShadowAngle) { @@ -185,11 +212,16 @@ } } + /** + * Set a shadow blur radius + * + * @member {number} + */ get dropShadowBlur() { return this._dropShadowBlur; } - set dropShadowBlur(dropShadowBlur) + set dropShadowBlur(dropShadowBlur) // eslint-disable-line require-jsdoc { if (this._dropShadowBlur !== dropShadowBlur) { @@ -198,11 +230,16 @@ } } + /** + * A fill style to be used on the dropshadow e.g 'red', '#00FF00' + * + * @member {string|number} + */ get dropShadowColor() { return this._dropShadowColor; } - set dropShadowColor(dropShadowColor) + set dropShadowColor(dropShadowColor) // eslint-disable-line require-jsdoc { const outputColor = getColor(dropShadowColor); if (this._dropShadowColor !== outputColor) @@ -212,11 +249,16 @@ } } + /** + * Set a distance of the drop shadow + * + * @member {number} + */ get dropShadowDistance() { return this._dropShadowDistance; } - set dropShadowDistance(dropShadowDistance) + set dropShadowDistance(dropShadowDistance) // eslint-disable-line require-jsdoc { if (this._dropShadowDistance !== dropShadowDistance) { @@ -225,11 +267,18 @@ } } + /** + * A canvas fillstyle that will be used on the text e.g 'red', '#00FF00'. + * Can be an array to create a gradient eg ['#000000','#FFFFFF'] + * {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} + * + * @member {string|string[]|number|number[]|CanvasGradient|CanvasPattern} + */ get fill() { return this._fill; } - set fill(fill) + set fill(fill) // eslint-disable-line require-jsdoc { const outputColor = getColor(fill); if (this._fill !== outputColor) @@ -239,11 +288,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this can change the type/direction of the gradient. + * See {@link PIXI.TEXT_GRADIENT} + * + * @member {number} + */ get fillGradientType() { return this._fillGradientType; } - set fillGradientType(fillGradientType) + set fillGradientType(fillGradientType) // eslint-disable-line require-jsdoc { if (this._fillGradientType !== fillGradientType) { @@ -252,11 +307,17 @@ } } + /** + * If fill is an array of colours to create a gradient, this array can set the stop points + * (numbers between 0 and 1) for the color, overriding the default behaviour of evenly spacing them. + * + * @member {number[]} + */ get fillGradientStops() { return this._fillGradientStops; } - set fillGradientStops(fillGradientStops) + set fillGradientStops(fillGradientStops) // eslint-disable-line require-jsdoc { if (!areArraysEqual(this._fillGradientStops,fillGradientStops)) { @@ -265,11 +326,16 @@ } } + /** + * The font family + * + * @member {string|string[]} + */ get fontFamily() { return this._fontFamily; } - set fontFamily(fontFamily) + set fontFamily(fontFamily) // eslint-disable-line require-jsdoc { if (this.fontFamily !== fontFamily) { @@ -278,11 +344,17 @@ } } + /** + * The font size + * (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * + * @member {number|string} + */ get fontSize() { return this._fontSize; } - set fontSize(fontSize) + set fontSize(fontSize) // eslint-disable-line require-jsdoc { if (this._fontSize !== fontSize) { @@ -291,11 +363,17 @@ } } + /** + * The font style + * ('normal', 'italic' or 'oblique') + * + * @member {string} + */ get fontStyle() { return this._fontStyle; } - set fontStyle(fontStyle) + set fontStyle(fontStyle) // eslint-disable-line require-jsdoc { if (this._fontStyle !== fontStyle) { @@ -304,11 +382,17 @@ } } + /** + * The font variant + * ('normal' or 'small-caps') + * + * @member {string} + */ get fontVariant() { return this._fontVariant; } - set fontVariant(fontVariant) + set fontVariant(fontVariant) // eslint-disable-line require-jsdoc { if (this._fontVariant !== fontVariant) { @@ -317,11 +401,17 @@ } } + /** + * The font weight + * ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') + * + * @member {string} + */ get fontWeight() { return this._fontWeight; } - set fontWeight(fontWeight) + set fontWeight(fontWeight) // eslint-disable-line require-jsdoc { if (this._fontWeight !== fontWeight) { @@ -330,11 +420,16 @@ } } + /** + * The amount of spacing between letters, default is 0 + * + * @member {number} + */ get letterSpacing() { return this._letterSpacing; } - set letterSpacing(letterSpacing) + set letterSpacing(letterSpacing) // eslint-disable-line require-jsdoc { if (this._letterSpacing !== letterSpacing) { @@ -343,11 +438,16 @@ } } + /** + * The line height, a number that represents the vertical space that a letter uses + * + * @member {number} + */ get lineHeight() { return this._lineHeight; } - set lineHeight(lineHeight) + set lineHeight(lineHeight) // eslint-disable-line require-jsdoc { if (this._lineHeight !== lineHeight) { @@ -356,11 +456,35 @@ } } + /** + * The space between lines + * + * @member {number} + */ + get leading() + { + return this._leading; + } + set leading(leading) // eslint-disable-line require-jsdoc + { + if (this._leading !== leading) + { + this._leading = leading; + this.styleID++; + } + } + + /** + * The lineJoin property sets the type of corner created, it can resolve spiked text issues. + * Default is 'miter' (creates a sharp corner). + * + * @member {string} + */ get lineJoin() { return this._lineJoin; } - set lineJoin(lineJoin) + set lineJoin(lineJoin) // eslint-disable-line require-jsdoc { if (this._lineJoin !== lineJoin) { @@ -369,11 +493,17 @@ } } + /** + * The miter limit to use when using the 'miter' lineJoin mode + * This can reduce or increase the spikiness of rendered text. + * + * @member {number} + */ get miterLimit() { return this._miterLimit; } - set miterLimit(miterLimit) + set miterLimit(miterLimit) // eslint-disable-line require-jsdoc { if (this._miterLimit !== miterLimit) { @@ -382,11 +512,17 @@ } } + /** + * Occasionally some fonts are cropped. Adding some padding will prevent this from happening + * by adding padding to all sides of the text. + * + * @member {number} + */ get padding() { return this._padding; } - set padding(padding) + set padding(padding) // eslint-disable-line require-jsdoc { if (this._padding !== padding) { @@ -395,11 +531,17 @@ } } + /** + * A canvas fillstyle that will be used on the text stroke + * e.g 'blue', '#FCFF00' + * + * @member {string|number} + */ get stroke() { return this._stroke; } - set stroke(stroke) + set stroke(stroke) // eslint-disable-line require-jsdoc { const outputColor = getColor(stroke); if (this._stroke !== outputColor) @@ -409,11 +551,17 @@ } } + /** + * A number that represents the thickness of the stroke. + * Default is 0 (no stroke) + * + * @member {number} + */ get strokeThickness() { return this._strokeThickness; } - set strokeThickness(strokeThickness) + set strokeThickness(strokeThickness) // eslint-disable-line require-jsdoc { if (this._strokeThickness !== strokeThickness) { @@ -422,11 +570,16 @@ } } + /** + * The baseline of the text that is rendered. + * + * @member {string} + */ get textBaseline() { return this._textBaseline; } - set textBaseline(textBaseline) + set textBaseline(textBaseline) // eslint-disable-line require-jsdoc { if (this._textBaseline !== textBaseline) { @@ -435,11 +588,16 @@ } } + /** + * Trim transparent borders + * + * @member {boolean} + */ get trim() { return this._trim; } - set trim(trim) + set trim(trim) // eslint-disable-line require-jsdoc { if (this._trim !== trim) { @@ -448,11 +606,16 @@ } } + /** + * Indicates if word wrap should be used + * + * @member {boolean} + */ get wordWrap() { return this._wordWrap; } - set wordWrap(wordWrap) + set wordWrap(wordWrap) // eslint-disable-line require-jsdoc { if (this._wordWrap !== wordWrap) { @@ -461,11 +624,16 @@ } } + /** + * The width at which text will wrap, it needs wordWrap to be set to true + * + * @member {number} + */ get wordWrapWidth() { return this._wordWrapWidth; } - set wordWrapWidth(wordWrapWidth) + set wordWrapWidth(wordWrapWidth) // eslint-disable-line require-jsdoc { if (this._wordWrapWidth !== wordWrapWidth) { diff --git a/src/core/textures/Texture.js b/src/core/textures/Texture.js index 3922e52..3a472be 100644 --- a/src/core/textures/Texture.js +++ b/src/core/textures/Texture.js @@ -521,7 +521,11 @@ { for (let i = 0; i < texture.textureCacheIds.length; ++i) { - delete TextureCache[texture.textureCacheIds[i]]; + // Check that texture matches the one being passed in before deleting it from the cache. + if (TextureCache[texture.textureCacheIds[i]] === texture) + { + delete TextureCache[texture.textureCacheIds[i]]; + } } texture.textureCacheIds.length = 0; diff --git a/src/core/ticker/Ticker.js b/src/core/ticker/Ticker.js index 1d58724..e07e0a6 100644 --- a/src/core/ticker/Ticker.js +++ b/src/core/ticker/Ticker.js @@ -81,9 +81,9 @@ * this value will have a precision of 1 µs. * * @member {number} - * @default 0 + * @default -1 */ - this.lastTime = 0; + this.lastTime = -1; /** * Factor of current {@link PIXI.ticker.Ticker#deltaTime}. diff --git a/src/mesh/canvas/CanvasMeshRenderer.js b/src/mesh/canvas/CanvasMeshRenderer.js index 5354e2c..6eaf2e0 100644 --- a/src/mesh/canvas/CanvasMeshRenderer.js +++ b/src/mesh/canvas/CanvasMeshRenderer.js @@ -244,6 +244,7 @@ ); context.restore(); + this.renderer.invalidateBlendMode(); } /** diff --git a/src/particles/ParticleContainer.js b/src/particles/ParticleContainer.js index 2196fb0..1c725d2 100644 --- a/src/particles/ParticleContainer.js +++ b/src/particles/ParticleContainer.js @@ -248,12 +248,7 @@ let finalWidth = 0; let finalHeight = 0; - const compositeOperation = renderer.blendModes[this.blendMode]; - - if (compositeOperation !== context.globalCompositeOperation) - { - context.globalCompositeOperation = compositeOperation; - } + renderer.setBlendMode(this.blendMode); context.globalAlpha = this.worldAlpha; diff --git a/test/core/Application.js b/test/core/Application.js index 00eb286..6d89c36 100644 --- a/test/core/Application.js +++ b/test/core/Application.js @@ -34,4 +34,18 @@ done(); }); }); + + it('should not start application before calling start method if options.autoStart is false', function (done) + { + const app = new PIXI.Application({ autoStart: false }); + + expect(app.ticker.started).to.be.false; + app.start(); + + app.ticker.addOnce(() => + { + app.destroy(); + done(); + }); + }); }); diff --git a/test/core/Texture.js b/test/core/Texture.js index 0a7919d..1fd9228 100644 --- a/test/core/Texture.js +++ b/test/core/Texture.js @@ -108,6 +108,25 @@ expect(PIXI.utils.TextureCache[NAME2]).to.equal(texture); }); + it('should not remove Texture from cache if Texture instance has been replaced', function () + { + cleanCache(); + + const texture = new PIXI.Texture(new PIXI.BaseTexture()); + const texture2 = new PIXI.Texture(new PIXI.BaseTexture()); + + PIXI.Texture.addToCache(texture, NAME); + expect(texture.textureCacheIds.indexOf(NAME)).to.equal(0); + expect(PIXI.utils.TextureCache[NAME]).to.equal(texture); + PIXI.Texture.addToCache(texture2, NAME); + expect(texture2.textureCacheIds.indexOf(NAME)).to.equal(0); + expect(PIXI.utils.TextureCache[NAME]).to.equal(texture2); + PIXI.Texture.removeFromCache(texture); + expect(texture.textureCacheIds.indexOf(NAME)).to.equal(-1); + expect(texture2.textureCacheIds.indexOf(NAME)).to.equal(0); + expect(PIXI.utils.TextureCache[NAME]).to.equal(texture2); + }); + it('destroying a destroyed texture should not throw an error', function () { const texture = new PIXI.Texture(new PIXI.BaseTexture());