diff --git a/src/core/const.js b/src/core/const.js index ef1d997..f10a252 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -1,28 +1,10 @@ /** * Constant values used in pixi * - * @mixin const + * @namespace PIXI.CONST */ module.exports = { /** - * Constant to identify the WEBGL Renderer Type - * - * @static - * @constant - * @property {number} WEBGL_RENDERER - */ - WEBGL_RENDERER: 1, - - /** - * Constant to identify the CANVAS Renderer Type - * - * @static - * @constant - * @property {number} CANVAS_RENDERER - */ - CANVAS_RENDERER: 2, - - /** * String of the current PIXI version * * @static @@ -32,6 +14,22 @@ VERSION: require('../../package.json').version, /** + * Constant to identify the Renderer Type. + * + * @static + * @constant + * @property {object} RENDERER_TYPE + * @property {number} RENDERER_TYPE.UNKNOWN + * @property {number} RENDERER_TYPE.WEBGL + * @property {number} RENDERER_TYPE.CANVAS + */ + RENDERER_TYPE: { + UNKNOWN: 0, + WEBGL: 1, + CANVAS: 2 + }, + + /** * Various blend modes supported by PIXI. IMPORTANT - The WebGL renderer only supports * the NORMAL, ADD, MULTIPLY and SCREEN blend modes. Anything else will silently act like * NORMAL. diff --git a/src/core/const.js b/src/core/const.js index ef1d997..f10a252 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -1,28 +1,10 @@ /** * Constant values used in pixi * - * @mixin const + * @namespace PIXI.CONST */ module.exports = { /** - * Constant to identify the WEBGL Renderer Type - * - * @static - * @constant - * @property {number} WEBGL_RENDERER - */ - WEBGL_RENDERER: 1, - - /** - * Constant to identify the CANVAS Renderer Type - * - * @static - * @constant - * @property {number} CANVAS_RENDERER - */ - CANVAS_RENDERER: 2, - - /** * String of the current PIXI version * * @static @@ -32,6 +14,22 @@ VERSION: require('../../package.json').version, /** + * Constant to identify the Renderer Type. + * + * @static + * @constant + * @property {object} RENDERER_TYPE + * @property {number} RENDERER_TYPE.UNKNOWN + * @property {number} RENDERER_TYPE.WEBGL + * @property {number} RENDERER_TYPE.CANVAS + */ + RENDERER_TYPE: { + UNKNOWN: 0, + WEBGL: 1, + CANVAS: 2 + }, + + /** * Various blend modes supported by PIXI. IMPORTANT - The WebGL renderer only supports * the NORMAL, ADD, MULTIPLY and SCREEN blend modes. Anything else will silently act like * NORMAL. diff --git a/src/core/renderers/SystemRenderer.js b/src/core/renderers/SystemRenderer.js new file mode 100644 index 0000000..bb0b894 --- /dev/null +++ b/src/core/renderers/SystemRenderer.js @@ -0,0 +1,237 @@ +var utils = require('../utils'), + CONST = require('../const'); + +/** + * The CanvasRenderer draws the scene and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. + * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :) + * + * @class + * @namespace PIXI + * @param system {string} The name of the system this renderer is for. + * @param [width=800] {number} the width of the canvas view + * @param [height=600] {number} the height of the canvas view + * @param [options] {object} The optional renderer parameters + * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional + * @param [options.transparent=false] {boolean} If the render view is transparent, default false + * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false + * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) + * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. + */ +function SystemRenderer(system, width, height, options) +{ + utils.sayHello(system); + + // prepare options + if (options) + { + for (var i in CONST.defaultRenderOptions) + { + if (typeof options[i] === 'undefined') + { + options[i] = CONST.defaultRenderOptions[i]; + } + } + } + else + { + options = CONST.defaultRenderOptions; + } + + /** + * The type of the renderer. + * + * @member {CONST.RENDERER_TYPE} + * @default CONT.RENDERER_TYPE.UNKNOWN + */ + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + /** + * The width of the canvas view + * + * @member {number} + * @default 800 + */ + this.width = width || 800; + + /** + * The height of the canvas view + * + * @member {number} + * @default 600 + */ + this.height = height || 600; + + /** + * The canvas element that everything is drawn to + * + * @member {HTMLCanvasElement} + */ + this.view = options.view || document.createElement('canvas'); + + /** + * The resolution of the renderer + * + * @member {number} + * @default 1 + */ + this.resolution = options.resolution; + + /** + * Whether the render view is transparent + * + * @member {boolean} + */ + this.transparent = options.transparent; + + /** + * Whether the render view should be resized automatically + * + * @member {boolean} + */ + this.autoResize = options.autoResize || false; + + /** + * Tracks the blend modes useful for this renderer. + * + * @member {object} + */ + this.blendModes = null; + + + /////////////////////////// + // TODO: Combine these! + + /** + * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. + * + * @member {boolean} + */ + this.preserveDrawingBuffer = options.preserveDrawingBuffer; + + /** + * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. + * If the scene is transparent Pixi will use clearRect to clear the canvas every frame. + * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. + * + * @member {boolean} + * @default + */ + this.clearBeforeRender = options.clearBeforeRender; + + + //////////////////////// + + /** + * The background color as a number. + * + * @member {number} + * @private + */ + this._backgroundColor = 0x000000; + + /** + * The background color as an [R, G, B] array. + * + * @member {number[]} + * @private + */ + this._backgroundColorRgb = [0, 0, 0]; + + /** + * The background color as a string. + * + * @member {string} + * @private + */ + this._backgroundColorString = '#000000'; + + this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter +} + +// constructor +SystemRenderer.prototype.constructor = SystemRenderer; +module.exports = SystemRenderer; + +utils.pluginTarget.mixin(SystemRenderer); +utils.eventTarget.mixin(SystemRenderer.prototype); + +Object.defineProperties(SystemRenderer.prototype, { + /** + * The background color to fill if not transparent + * + * @member {number} + * @memberof SystemRenderer# + */ + backgroundColor: + { + get: function () + { + return this._backgroundColor; + }, + set: function (val) + { + this._backgroundColor = val; + this._backgroundColorString = utils.hex2string(val); + utils.hex2rgb(val, this._backgroundColorRgb); + } + } +}); + +/** + * Resizes the canvas view to the specified width and height + * + * @param width {number} the new width of the canvas view + * @param height {number} the new height of the canvas view + */ +SystemRenderer.prototype.resize = function (width, height) { + this.width = width * this.resolution; + this.height = height * this.resolution; + + this.view.width = this.width; + this.view.height = this.height; + + if (this.autoResize) + { + this.view.style.width = this.width / this.resolution + 'px'; + this.view.style.height = this.height / this.resolution + 'px'; + } +}; + +/** + * Removes everything from the renderer and optionally removes the Canvas DOM element. + * + * @param [removeView=false] {boolean} Removes the Canvas element from the DOM. + */ +SystemRenderer.prototype.destroy = function (removeView) { + if (removeView && this.view.parent) + { + this.view.parent.removeChild(this.view); + } + + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + this.width = 0; + this.height = 0; + + this.view = null; + + this.resolution = 0; + + this.transparent = false; + + this.autoResize = false; + + this.blendModes = null; + + this.preserveDrawingBuffer = false; + this.clearBeforeRender = false; + + this._backgroundColor = 0; + this._backgroundColorRgb = null; + this._backgroundColorString = null; + + this.destroyPlugins(); +}; diff --git a/src/core/const.js b/src/core/const.js index ef1d997..f10a252 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -1,28 +1,10 @@ /** * Constant values used in pixi * - * @mixin const + * @namespace PIXI.CONST */ module.exports = { /** - * Constant to identify the WEBGL Renderer Type - * - * @static - * @constant - * @property {number} WEBGL_RENDERER - */ - WEBGL_RENDERER: 1, - - /** - * Constant to identify the CANVAS Renderer Type - * - * @static - * @constant - * @property {number} CANVAS_RENDERER - */ - CANVAS_RENDERER: 2, - - /** * String of the current PIXI version * * @static @@ -32,6 +14,22 @@ VERSION: require('../../package.json').version, /** + * Constant to identify the Renderer Type. + * + * @static + * @constant + * @property {object} RENDERER_TYPE + * @property {number} RENDERER_TYPE.UNKNOWN + * @property {number} RENDERER_TYPE.WEBGL + * @property {number} RENDERER_TYPE.CANVAS + */ + RENDERER_TYPE: { + UNKNOWN: 0, + WEBGL: 1, + CANVAS: 2 + }, + + /** * Various blend modes supported by PIXI. IMPORTANT - The WebGL renderer only supports * the NORMAL, ADD, MULTIPLY and SCREEN blend modes. Anything else will silently act like * NORMAL. diff --git a/src/core/renderers/SystemRenderer.js b/src/core/renderers/SystemRenderer.js new file mode 100644 index 0000000..bb0b894 --- /dev/null +++ b/src/core/renderers/SystemRenderer.js @@ -0,0 +1,237 @@ +var utils = require('../utils'), + CONST = require('../const'); + +/** + * The CanvasRenderer draws the scene and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. + * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :) + * + * @class + * @namespace PIXI + * @param system {string} The name of the system this renderer is for. + * @param [width=800] {number} the width of the canvas view + * @param [height=600] {number} the height of the canvas view + * @param [options] {object} The optional renderer parameters + * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional + * @param [options.transparent=false] {boolean} If the render view is transparent, default false + * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false + * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) + * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. + */ +function SystemRenderer(system, width, height, options) +{ + utils.sayHello(system); + + // prepare options + if (options) + { + for (var i in CONST.defaultRenderOptions) + { + if (typeof options[i] === 'undefined') + { + options[i] = CONST.defaultRenderOptions[i]; + } + } + } + else + { + options = CONST.defaultRenderOptions; + } + + /** + * The type of the renderer. + * + * @member {CONST.RENDERER_TYPE} + * @default CONT.RENDERER_TYPE.UNKNOWN + */ + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + /** + * The width of the canvas view + * + * @member {number} + * @default 800 + */ + this.width = width || 800; + + /** + * The height of the canvas view + * + * @member {number} + * @default 600 + */ + this.height = height || 600; + + /** + * The canvas element that everything is drawn to + * + * @member {HTMLCanvasElement} + */ + this.view = options.view || document.createElement('canvas'); + + /** + * The resolution of the renderer + * + * @member {number} + * @default 1 + */ + this.resolution = options.resolution; + + /** + * Whether the render view is transparent + * + * @member {boolean} + */ + this.transparent = options.transparent; + + /** + * Whether the render view should be resized automatically + * + * @member {boolean} + */ + this.autoResize = options.autoResize || false; + + /** + * Tracks the blend modes useful for this renderer. + * + * @member {object} + */ + this.blendModes = null; + + + /////////////////////////// + // TODO: Combine these! + + /** + * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. + * + * @member {boolean} + */ + this.preserveDrawingBuffer = options.preserveDrawingBuffer; + + /** + * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. + * If the scene is transparent Pixi will use clearRect to clear the canvas every frame. + * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. + * + * @member {boolean} + * @default + */ + this.clearBeforeRender = options.clearBeforeRender; + + + //////////////////////// + + /** + * The background color as a number. + * + * @member {number} + * @private + */ + this._backgroundColor = 0x000000; + + /** + * The background color as an [R, G, B] array. + * + * @member {number[]} + * @private + */ + this._backgroundColorRgb = [0, 0, 0]; + + /** + * The background color as a string. + * + * @member {string} + * @private + */ + this._backgroundColorString = '#000000'; + + this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter +} + +// constructor +SystemRenderer.prototype.constructor = SystemRenderer; +module.exports = SystemRenderer; + +utils.pluginTarget.mixin(SystemRenderer); +utils.eventTarget.mixin(SystemRenderer.prototype); + +Object.defineProperties(SystemRenderer.prototype, { + /** + * The background color to fill if not transparent + * + * @member {number} + * @memberof SystemRenderer# + */ + backgroundColor: + { + get: function () + { + return this._backgroundColor; + }, + set: function (val) + { + this._backgroundColor = val; + this._backgroundColorString = utils.hex2string(val); + utils.hex2rgb(val, this._backgroundColorRgb); + } + } +}); + +/** + * Resizes the canvas view to the specified width and height + * + * @param width {number} the new width of the canvas view + * @param height {number} the new height of the canvas view + */ +SystemRenderer.prototype.resize = function (width, height) { + this.width = width * this.resolution; + this.height = height * this.resolution; + + this.view.width = this.width; + this.view.height = this.height; + + if (this.autoResize) + { + this.view.style.width = this.width / this.resolution + 'px'; + this.view.style.height = this.height / this.resolution + 'px'; + } +}; + +/** + * Removes everything from the renderer and optionally removes the Canvas DOM element. + * + * @param [removeView=false] {boolean} Removes the Canvas element from the DOM. + */ +SystemRenderer.prototype.destroy = function (removeView) { + if (removeView && this.view.parent) + { + this.view.parent.removeChild(this.view); + } + + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + this.width = 0; + this.height = 0; + + this.view = null; + + this.resolution = 0; + + this.transparent = false; + + this.autoResize = false; + + this.blendModes = null; + + this.preserveDrawingBuffer = false; + this.clearBeforeRender = false; + + this._backgroundColor = 0; + this._backgroundColorRgb = null; + this._backgroundColorString = null; + + this.destroyPlugins(); +}; diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index f43e637..716cd0e 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -1,4 +1,5 @@ -var CanvasMaskManager = require('./utils/CanvasMaskManager'), +var SystemRenderer = require('../SystemRenderer'), + CanvasMaskManager = require('./utils/CanvasMaskManager'), utils = require('../../utils'), math = require('../../math'), CONST = require('../../const'); @@ -15,113 +16,20 @@ * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional * @param [options.transparent=false] {boolean} If the render view is transparent, default false * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false + * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 - * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. */ function CanvasRenderer(width, height, options) { - utils.sayHello('Canvas'); + SystemRenderer.call(this, 'Canvas', width, height, options); - if (options) - { - for (var i in CONST.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') - { - options[i] = CONST.defaultRenderOptions[i]; - } - } - } - else - { - options = CONST.defaultRenderOptions; - } + this.type = CONST.RENDERER_TYPE.CANVAS; /** - * The renderer type. + * The canvas 2d context that everything is drawn with. * - * @member {number} - */ - this.type = CONST.CANVAS_RENDERER; - - /** - * The resolution of the canvas. - * - * @member {number} - */ - this.resolution = options.resolution; - - /** - * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. - * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. - * If the scene is transparent Pixi will use clearRect to clear the canvas every frame. - * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. - * - * @member {boolean} - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The background color as a number. - * - * @member {number} - * @private - */ - this._backgroundColor = 0x000000; - - /** - * The background color as a string. - * - * @member {string} - * @private - */ - this._backgroundColorString = '#000000'; - - this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter - - /** - * Whether the render view is transparent - * - * @member {boolean} - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @member {boolean} - */ - this.autoResize = options.autoResize || false; - - /** - * The width of the canvas view - * - * @member {number} - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @member {number} - * @default 600 - */ - this.height = height || 600; - - this.width *= this.resolution; - this.height *= this.resolution; - - /** - * The canvas element that everything is drawn to. - * - * @member {HTMLCanvasElement} - */ - this.view = options.view || document.createElement('canvas'); - - /** - * The canvas 2d context that everything is drawn with * @member {CanvasRenderingContext2D} */ this.context = this.view.getContext('2d', { alpha: this.transparent }); @@ -133,18 +41,9 @@ */ this.refresh = true; - this.view.width = this.width * this.resolution; - this.view.height = this.height * this.resolution; - /** - * Internal var. + * Instance of a CanvasMaskManager, handles masking when using the canvas renderer. * - * @member {number} - */ - this.count = 0; - - /** - * Instance of a CanvasMaskManager, handles masking when using the canvas renderer * @member {CanvasMaskManager} */ this.maskManager = new CanvasMaskManager(); @@ -157,71 +56,68 @@ */ this.roundPixels = false; - this.scaleMode = null; + /** + * Tracks the active scale mode for this renderer. + * + * @member {CONST.SCALE_MODE} + */ + this.currentScaleMode = CONST.scaleModes.DEFAULT; - this.smoothProperty = null; - - if (this.context.imageSmoothingEnabled) - { - this.smoothProperty = 'imageSmoothingEnabled'; - } - else if (this.context.webkitImageSmoothingEnabled) - { - this.smoothProperty = 'webkitImageSmoothingEnabled'; - } - else if (this.context.mozImageSmoothingEnabled) - { - this.smoothProperty = 'mozImageSmoothingEnabled'; - } - else if (this.context.oImageSmoothingEnabled) - { - this.smoothProperty = 'oImageSmoothingEnabled'; - } - else if (this.context.msImageSmoothingEnabled) - { - this.smoothProperty = 'msImageSmoothingEnabled'; - } - + /** + * Tracks the active blend mode for this renderer. + * + * @member {CONST.SCALE_MODE} + */ this.currentBlendMode = CONST.blendModes.NORMAL; - this.blendModes = null; + /** + * The canvas property used to set the canvas smoothing property. + * + * @member {string} + */ + this.smoothProperty = 'imageSmoothingEnabled'; + + if (!this.context.imageSmoothingEnabled) + { + if (this.context.webkitImageSmoothingEnabled) + { + this.smoothProperty = 'webkitImageSmoothingEnabled'; + } + else if (this.context.mozImageSmoothingEnabled) + { + this.smoothProperty = 'mozImageSmoothingEnabled'; + } + else if (this.context.oImageSmoothingEnabled) + { + this.smoothProperty = 'oImageSmoothingEnabled'; + } + else if (this.context.msImageSmoothingEnabled) + { + this.smoothProperty = 'msImageSmoothingEnabled'; + } + } this._mapBlendModes(); /** * This temporary display object used as the parent of the currently being rendered item + * * @member DisplayObject * @private */ - this._tempDisplayObjectParent = {worldTransform:new math.Matrix(), worldAlpha:1}; + this._tempDisplayObjectParent = { + worldTransform: new math.Matrix(), + worldAlpha: 1 + }; this.resize(width, height); } // constructor +CanvasRenderer.prototype = Object.create(SystemRenderer); CanvasRenderer.prototype.constructor = CanvasRenderer; module.exports = CanvasRenderer; -Object.defineProperties(CanvasRenderer.prototype, { - /** - * The background color to fill if not transparent - * - * @member {number} - * @memberof CanvasRenderer# - */ - backgroundColor: { - get: function () - { - return this._backgroundColor; - }, - set: function (val) - { - this._backgroundColor = val; - this._backgroundColorString = utils.hex2string(val); - } - } -}); - /** * Renders the object to this canvas view * @@ -237,7 +133,7 @@ object.parent = cacheParent; - this.context.setTransform(1,0,0,1,0,0); + this.context.setTransform(1, 0, 0, 1, 0, 0); this.context.globalAlpha = 1; @@ -273,35 +169,22 @@ */ CanvasRenderer.prototype.destroy = function (removeView) { - if (removeView && this.view.parent) - { - this.view.parent.removeChild(this.view); - } + // call the base destroy + SystemRenderer.prototype.destroy.call(this, removeView); - this.view = null; this.context = null; + + this.refresh = true; + + this.maskManager.destroy(); this.maskManager = null; -}; -/** - * Resizes the canvas view to the specified width and height - * - * @param width {number} the new width of the canvas view - * @param height {number} the new height of the canvas view - */ -CanvasRenderer.prototype.resize = function (width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; + this.roundPixels = false; - this.view.width = this.width; - this.view.height = this.height; + this.currentScaleMode = 0; + this.currentBlendMode = 0; - if (this.autoResize) - { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } + this.smoothProperty = null; }; /** diff --git a/src/core/const.js b/src/core/const.js index ef1d997..f10a252 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -1,28 +1,10 @@ /** * Constant values used in pixi * - * @mixin const + * @namespace PIXI.CONST */ module.exports = { /** - * Constant to identify the WEBGL Renderer Type - * - * @static - * @constant - * @property {number} WEBGL_RENDERER - */ - WEBGL_RENDERER: 1, - - /** - * Constant to identify the CANVAS Renderer Type - * - * @static - * @constant - * @property {number} CANVAS_RENDERER - */ - CANVAS_RENDERER: 2, - - /** * String of the current PIXI version * * @static @@ -32,6 +14,22 @@ VERSION: require('../../package.json').version, /** + * Constant to identify the Renderer Type. + * + * @static + * @constant + * @property {object} RENDERER_TYPE + * @property {number} RENDERER_TYPE.UNKNOWN + * @property {number} RENDERER_TYPE.WEBGL + * @property {number} RENDERER_TYPE.CANVAS + */ + RENDERER_TYPE: { + UNKNOWN: 0, + WEBGL: 1, + CANVAS: 2 + }, + + /** * Various blend modes supported by PIXI. IMPORTANT - The WebGL renderer only supports * the NORMAL, ADD, MULTIPLY and SCREEN blend modes. Anything else will silently act like * NORMAL. diff --git a/src/core/renderers/SystemRenderer.js b/src/core/renderers/SystemRenderer.js new file mode 100644 index 0000000..bb0b894 --- /dev/null +++ b/src/core/renderers/SystemRenderer.js @@ -0,0 +1,237 @@ +var utils = require('../utils'), + CONST = require('../const'); + +/** + * The CanvasRenderer draws the scene and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. + * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :) + * + * @class + * @namespace PIXI + * @param system {string} The name of the system this renderer is for. + * @param [width=800] {number} the width of the canvas view + * @param [height=600] {number} the height of the canvas view + * @param [options] {object} The optional renderer parameters + * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional + * @param [options.transparent=false] {boolean} If the render view is transparent, default false + * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false + * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) + * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. + */ +function SystemRenderer(system, width, height, options) +{ + utils.sayHello(system); + + // prepare options + if (options) + { + for (var i in CONST.defaultRenderOptions) + { + if (typeof options[i] === 'undefined') + { + options[i] = CONST.defaultRenderOptions[i]; + } + } + } + else + { + options = CONST.defaultRenderOptions; + } + + /** + * The type of the renderer. + * + * @member {CONST.RENDERER_TYPE} + * @default CONT.RENDERER_TYPE.UNKNOWN + */ + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + /** + * The width of the canvas view + * + * @member {number} + * @default 800 + */ + this.width = width || 800; + + /** + * The height of the canvas view + * + * @member {number} + * @default 600 + */ + this.height = height || 600; + + /** + * The canvas element that everything is drawn to + * + * @member {HTMLCanvasElement} + */ + this.view = options.view || document.createElement('canvas'); + + /** + * The resolution of the renderer + * + * @member {number} + * @default 1 + */ + this.resolution = options.resolution; + + /** + * Whether the render view is transparent + * + * @member {boolean} + */ + this.transparent = options.transparent; + + /** + * Whether the render view should be resized automatically + * + * @member {boolean} + */ + this.autoResize = options.autoResize || false; + + /** + * Tracks the blend modes useful for this renderer. + * + * @member {object} + */ + this.blendModes = null; + + + /////////////////////////// + // TODO: Combine these! + + /** + * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. + * + * @member {boolean} + */ + this.preserveDrawingBuffer = options.preserveDrawingBuffer; + + /** + * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. + * If the scene is transparent Pixi will use clearRect to clear the canvas every frame. + * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. + * + * @member {boolean} + * @default + */ + this.clearBeforeRender = options.clearBeforeRender; + + + //////////////////////// + + /** + * The background color as a number. + * + * @member {number} + * @private + */ + this._backgroundColor = 0x000000; + + /** + * The background color as an [R, G, B] array. + * + * @member {number[]} + * @private + */ + this._backgroundColorRgb = [0, 0, 0]; + + /** + * The background color as a string. + * + * @member {string} + * @private + */ + this._backgroundColorString = '#000000'; + + this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter +} + +// constructor +SystemRenderer.prototype.constructor = SystemRenderer; +module.exports = SystemRenderer; + +utils.pluginTarget.mixin(SystemRenderer); +utils.eventTarget.mixin(SystemRenderer.prototype); + +Object.defineProperties(SystemRenderer.prototype, { + /** + * The background color to fill if not transparent + * + * @member {number} + * @memberof SystemRenderer# + */ + backgroundColor: + { + get: function () + { + return this._backgroundColor; + }, + set: function (val) + { + this._backgroundColor = val; + this._backgroundColorString = utils.hex2string(val); + utils.hex2rgb(val, this._backgroundColorRgb); + } + } +}); + +/** + * Resizes the canvas view to the specified width and height + * + * @param width {number} the new width of the canvas view + * @param height {number} the new height of the canvas view + */ +SystemRenderer.prototype.resize = function (width, height) { + this.width = width * this.resolution; + this.height = height * this.resolution; + + this.view.width = this.width; + this.view.height = this.height; + + if (this.autoResize) + { + this.view.style.width = this.width / this.resolution + 'px'; + this.view.style.height = this.height / this.resolution + 'px'; + } +}; + +/** + * Removes everything from the renderer and optionally removes the Canvas DOM element. + * + * @param [removeView=false] {boolean} Removes the Canvas element from the DOM. + */ +SystemRenderer.prototype.destroy = function (removeView) { + if (removeView && this.view.parent) + { + this.view.parent.removeChild(this.view); + } + + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + this.width = 0; + this.height = 0; + + this.view = null; + + this.resolution = 0; + + this.transparent = false; + + this.autoResize = false; + + this.blendModes = null; + + this.preserveDrawingBuffer = false; + this.clearBeforeRender = false; + + this._backgroundColor = 0; + this._backgroundColorRgb = null; + this._backgroundColorString = null; + + this.destroyPlugins(); +}; diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index f43e637..716cd0e 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -1,4 +1,5 @@ -var CanvasMaskManager = require('./utils/CanvasMaskManager'), +var SystemRenderer = require('../SystemRenderer'), + CanvasMaskManager = require('./utils/CanvasMaskManager'), utils = require('../../utils'), math = require('../../math'), CONST = require('../../const'); @@ -15,113 +16,20 @@ * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional * @param [options.transparent=false] {boolean} If the render view is transparent, default false * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false + * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 - * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. */ function CanvasRenderer(width, height, options) { - utils.sayHello('Canvas'); + SystemRenderer.call(this, 'Canvas', width, height, options); - if (options) - { - for (var i in CONST.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') - { - options[i] = CONST.defaultRenderOptions[i]; - } - } - } - else - { - options = CONST.defaultRenderOptions; - } + this.type = CONST.RENDERER_TYPE.CANVAS; /** - * The renderer type. + * The canvas 2d context that everything is drawn with. * - * @member {number} - */ - this.type = CONST.CANVAS_RENDERER; - - /** - * The resolution of the canvas. - * - * @member {number} - */ - this.resolution = options.resolution; - - /** - * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. - * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. - * If the scene is transparent Pixi will use clearRect to clear the canvas every frame. - * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. - * - * @member {boolean} - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The background color as a number. - * - * @member {number} - * @private - */ - this._backgroundColor = 0x000000; - - /** - * The background color as a string. - * - * @member {string} - * @private - */ - this._backgroundColorString = '#000000'; - - this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter - - /** - * Whether the render view is transparent - * - * @member {boolean} - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @member {boolean} - */ - this.autoResize = options.autoResize || false; - - /** - * The width of the canvas view - * - * @member {number} - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @member {number} - * @default 600 - */ - this.height = height || 600; - - this.width *= this.resolution; - this.height *= this.resolution; - - /** - * The canvas element that everything is drawn to. - * - * @member {HTMLCanvasElement} - */ - this.view = options.view || document.createElement('canvas'); - - /** - * The canvas 2d context that everything is drawn with * @member {CanvasRenderingContext2D} */ this.context = this.view.getContext('2d', { alpha: this.transparent }); @@ -133,18 +41,9 @@ */ this.refresh = true; - this.view.width = this.width * this.resolution; - this.view.height = this.height * this.resolution; - /** - * Internal var. + * Instance of a CanvasMaskManager, handles masking when using the canvas renderer. * - * @member {number} - */ - this.count = 0; - - /** - * Instance of a CanvasMaskManager, handles masking when using the canvas renderer * @member {CanvasMaskManager} */ this.maskManager = new CanvasMaskManager(); @@ -157,71 +56,68 @@ */ this.roundPixels = false; - this.scaleMode = null; + /** + * Tracks the active scale mode for this renderer. + * + * @member {CONST.SCALE_MODE} + */ + this.currentScaleMode = CONST.scaleModes.DEFAULT; - this.smoothProperty = null; - - if (this.context.imageSmoothingEnabled) - { - this.smoothProperty = 'imageSmoothingEnabled'; - } - else if (this.context.webkitImageSmoothingEnabled) - { - this.smoothProperty = 'webkitImageSmoothingEnabled'; - } - else if (this.context.mozImageSmoothingEnabled) - { - this.smoothProperty = 'mozImageSmoothingEnabled'; - } - else if (this.context.oImageSmoothingEnabled) - { - this.smoothProperty = 'oImageSmoothingEnabled'; - } - else if (this.context.msImageSmoothingEnabled) - { - this.smoothProperty = 'msImageSmoothingEnabled'; - } - + /** + * Tracks the active blend mode for this renderer. + * + * @member {CONST.SCALE_MODE} + */ this.currentBlendMode = CONST.blendModes.NORMAL; - this.blendModes = null; + /** + * The canvas property used to set the canvas smoothing property. + * + * @member {string} + */ + this.smoothProperty = 'imageSmoothingEnabled'; + + if (!this.context.imageSmoothingEnabled) + { + if (this.context.webkitImageSmoothingEnabled) + { + this.smoothProperty = 'webkitImageSmoothingEnabled'; + } + else if (this.context.mozImageSmoothingEnabled) + { + this.smoothProperty = 'mozImageSmoothingEnabled'; + } + else if (this.context.oImageSmoothingEnabled) + { + this.smoothProperty = 'oImageSmoothingEnabled'; + } + else if (this.context.msImageSmoothingEnabled) + { + this.smoothProperty = 'msImageSmoothingEnabled'; + } + } this._mapBlendModes(); /** * This temporary display object used as the parent of the currently being rendered item + * * @member DisplayObject * @private */ - this._tempDisplayObjectParent = {worldTransform:new math.Matrix(), worldAlpha:1}; + this._tempDisplayObjectParent = { + worldTransform: new math.Matrix(), + worldAlpha: 1 + }; this.resize(width, height); } // constructor +CanvasRenderer.prototype = Object.create(SystemRenderer); CanvasRenderer.prototype.constructor = CanvasRenderer; module.exports = CanvasRenderer; -Object.defineProperties(CanvasRenderer.prototype, { - /** - * The background color to fill if not transparent - * - * @member {number} - * @memberof CanvasRenderer# - */ - backgroundColor: { - get: function () - { - return this._backgroundColor; - }, - set: function (val) - { - this._backgroundColor = val; - this._backgroundColorString = utils.hex2string(val); - } - } -}); - /** * Renders the object to this canvas view * @@ -237,7 +133,7 @@ object.parent = cacheParent; - this.context.setTransform(1,0,0,1,0,0); + this.context.setTransform(1, 0, 0, 1, 0, 0); this.context.globalAlpha = 1; @@ -273,35 +169,22 @@ */ CanvasRenderer.prototype.destroy = function (removeView) { - if (removeView && this.view.parent) - { - this.view.parent.removeChild(this.view); - } + // call the base destroy + SystemRenderer.prototype.destroy.call(this, removeView); - this.view = null; this.context = null; + + this.refresh = true; + + this.maskManager.destroy(); this.maskManager = null; -}; -/** - * Resizes the canvas view to the specified width and height - * - * @param width {number} the new width of the canvas view - * @param height {number} the new height of the canvas view - */ -CanvasRenderer.prototype.resize = function (width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; + this.roundPixels = false; - this.view.width = this.width; - this.view.height = this.height; + this.currentScaleMode = 0; + this.currentBlendMode = 0; - if (this.autoResize) - { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } + this.smoothProperty = null; }; /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 268ef7b..eaa78df 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -1,4 +1,5 @@ -var ShaderManager = require('./managers/ShaderManager'), +var SystemRenderer = require('../SystemRenderer'), + ShaderManager = require('./managers/ShaderManager'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), FilterManager = require('./managers/FilterManager'), @@ -25,148 +26,41 @@ * @param [options.transparent=false] {boolean} If the render view is transparent, default false * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. + * @param [options.preserveDrawingBuffer=false] {boolean} enables drawing buffer preservation, enable this if + * you need to call toDataUrl on the webgl context. */ function WebGLRenderer(width, height, options) { - utils.sayHello('webGL'); + SystemRenderer.call(this, 'WebGL', width, height, options); - WebGLRenderer._TEMP__ = this; + this.type = CONST.RENDERER_TYPE.WEBGL; - if (options) - { - for (var i in CONST.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') - { - options[i] = CONST.defaultRenderOptions[i]; - } - } - } - else - { - options = CONST.defaultRenderOptions; - } - this.uuid = utils.uuid(); + this._boundUpdateTexture = this.updateTexture.bind(this); + this._boundDestroyTexture = this.destroyTexture.bind(this); + this._boundContextLost = this.handleContextLost.bind(this); + this._boundContextRestored = this.handleContextRestored.bind(this); + + this.view.addEventListener('webglcontextlost', this._boundContextLost, false); + this.view.addEventListener('webglcontextrestored', this._boundContextRestored, false); /** - * @member {number} - */ - this.type = CONST.WEBGL_RENDERER; - - /** - * The resolution of the renderer + * The options passed in to create a new webgl context. * - * @member {number} - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @member {boolean} - */ - this.transparent = options.transparent; - - /** - * The background color as a number. - * - * @member {number} - * @private - */ - this._backgroundColor = 0x000000; - - /** - * The background color as an [R, G, B] array. - * - * @member {number[]} - * @private - */ - this._backgroundColorRgb = [0, 0, 0]; - - this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter - - /** - * Whether the render view should be resized automatically - * - * @member {boolean} - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @member {boolean} - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the renderer is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the renderer is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @member {boolean} - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @member {number} - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @member {number} - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @member {HTMLCanvasElement} - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @member {Function} - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @member {Function} - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** * @member {object} * @private */ this._contextOptions = { alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, + antialias: options.antialias, + premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', + stencil: true, preserveDrawingBuffer: options.preserveDrawingBuffer }; - /** * Counter for the number of draws made each frame * @@ -174,26 +68,30 @@ */ this.drawCount = 0; - // time to create the render managers! each one focuses on managing a state in webGL - - - /** - * Deals with managing the shader programs and their attribs + * Deals with managing the shader programs and their attribs. + * * @member {ShaderManager} */ this.shaderManager = new ShaderManager(this); /** - * Manages the masks using the stencil buffer + * Manages the masks using the stencil buffer. + * * @member {MaskManager} */ this.maskManager = new MaskManager(this); + /** + * Manages the stencil buffer. + * + * @member {StencilManager} + */ this.stencilManager = new StencilManager(this); /** - * Manages the filters + * Manages the filters. + * * @member {FilterManager} */ this.filterManager = new FilterManager(this); @@ -205,14 +103,6 @@ */ this.blendModeManager = new BlendModeManager(this); - this.blendModes = null; - - - - this._boundUpdateTexture = this.updateTexture.bind(this); - this._boundDestroyTexture = this.destroyTexture.bind(this); - - this.currentRenderTarget = this.renderTarget; /** @@ -234,35 +124,12 @@ } // constructor +WebGLRenderer.prototype = Object.create(SystemRenderer); WebGLRenderer.prototype.constructor = WebGLRenderer; module.exports = WebGLRenderer; WebGLRenderer.glContextId = 0; -utils.pluginTarget.mixin(WebGLRenderer); -utils.eventTarget.mixin(WebGLRenderer.prototype); - -Object.defineProperties(WebGLRenderer.prototype, { - /** - * The background color to fill if not transparent - * - * @member {number} - * @memberof WebGLRenderer# - */ - backgroundColor: - { - get: function () - { - return this._backgroundColor; - }, - set: function (val) - { - this._backgroundColor = val; - utils.hex2rgb(val, this._backgroundColorRgb); - } - } -}); - /** * * @private @@ -291,7 +158,7 @@ this.emit('context', gl); - // now resize and we are good to go! + // setup the width/height properties and gl viewport this.resize(this.width, this.height); }; @@ -394,17 +261,7 @@ */ WebGLRenderer.prototype.resize = function (width, height) { - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) - { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } + SystemRenderer.prototype.resize.call(this, width, height); this.gl.viewport(0, 0, this.width, this.height); @@ -518,56 +375,34 @@ */ WebGLRenderer.prototype.destroy = function (removeView) { - if (removeView && this.view.parent) - { - this.view.parent.removeChild(this.view); - } - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); + this.view.removeEventListener('webglcontextlost', this._boundContextLost); + this.view.removeEventListener('webglcontextrestored', this._boundContextRestored); - // time to create the render managers! each one focuses on managine a state in webGL + // call base destroy + SystemRenderer.prototype.destroy.call(this, removeView); + + this.uuid = 0; + + // destroy the managers this.shaderManager.destroy(); this.maskManager.destroy(); + this.stencilManager.destroy(); this.filterManager.destroy(); - this.destroyPlugins(); - - // this.uuid = utils.uuid(); - // this.type = CONST.WEBGL_RENDERER; - - // this.resolution = options.resolution; - // this.transparent = options.transparent; - - this._backgroundColor = 0x000000; - this._backgroundColorRgb = null; - - // this.backgroundColor = null; - // this.autoResize = options.autoResize || false; - // this.preserveDrawingBuffer = options.preserveDrawingBuffer; - // this.clearBeforeRender = options.clearBeforeRender; - // this.width = width || 800; - // this.height = height || 600; - - this.view = null; - - this.contextLostBound = null; - this.contextRestoredBound = null; - - this._contextOptions = null; - - this.drawCount = 0; - this.shaderManager = null; this.maskManager = null; this.filterManager = null; this.blendModeManager = null; - this.blendModes = null; + this._boundContextLost = null; + this._boundContextRestored = null; + + this._contextOptions = null; + + this.drawCount = 0; this.gl = null; - this.blendModes = null; }; /** diff --git a/src/core/const.js b/src/core/const.js index ef1d997..f10a252 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -1,28 +1,10 @@ /** * Constant values used in pixi * - * @mixin const + * @namespace PIXI.CONST */ module.exports = { /** - * Constant to identify the WEBGL Renderer Type - * - * @static - * @constant - * @property {number} WEBGL_RENDERER - */ - WEBGL_RENDERER: 1, - - /** - * Constant to identify the CANVAS Renderer Type - * - * @static - * @constant - * @property {number} CANVAS_RENDERER - */ - CANVAS_RENDERER: 2, - - /** * String of the current PIXI version * * @static @@ -32,6 +14,22 @@ VERSION: require('../../package.json').version, /** + * Constant to identify the Renderer Type. + * + * @static + * @constant + * @property {object} RENDERER_TYPE + * @property {number} RENDERER_TYPE.UNKNOWN + * @property {number} RENDERER_TYPE.WEBGL + * @property {number} RENDERER_TYPE.CANVAS + */ + RENDERER_TYPE: { + UNKNOWN: 0, + WEBGL: 1, + CANVAS: 2 + }, + + /** * Various blend modes supported by PIXI. IMPORTANT - The WebGL renderer only supports * the NORMAL, ADD, MULTIPLY and SCREEN blend modes. Anything else will silently act like * NORMAL. diff --git a/src/core/renderers/SystemRenderer.js b/src/core/renderers/SystemRenderer.js new file mode 100644 index 0000000..bb0b894 --- /dev/null +++ b/src/core/renderers/SystemRenderer.js @@ -0,0 +1,237 @@ +var utils = require('../utils'), + CONST = require('../const'); + +/** + * The CanvasRenderer draws the scene and all its content onto a 2d canvas. This renderer should be used for browsers that do not support webGL. + * Don't forget to add the CanvasRenderer.view to your DOM or you will not see anything :) + * + * @class + * @namespace PIXI + * @param system {string} The name of the system this renderer is for. + * @param [width=800] {number} the width of the canvas view + * @param [height=600] {number} the height of the canvas view + * @param [options] {object} The optional renderer parameters + * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional + * @param [options.transparent=false] {boolean} If the render view is transparent, default false + * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false + * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) + * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. + */ +function SystemRenderer(system, width, height, options) +{ + utils.sayHello(system); + + // prepare options + if (options) + { + for (var i in CONST.defaultRenderOptions) + { + if (typeof options[i] === 'undefined') + { + options[i] = CONST.defaultRenderOptions[i]; + } + } + } + else + { + options = CONST.defaultRenderOptions; + } + + /** + * The type of the renderer. + * + * @member {CONST.RENDERER_TYPE} + * @default CONT.RENDERER_TYPE.UNKNOWN + */ + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + /** + * The width of the canvas view + * + * @member {number} + * @default 800 + */ + this.width = width || 800; + + /** + * The height of the canvas view + * + * @member {number} + * @default 600 + */ + this.height = height || 600; + + /** + * The canvas element that everything is drawn to + * + * @member {HTMLCanvasElement} + */ + this.view = options.view || document.createElement('canvas'); + + /** + * The resolution of the renderer + * + * @member {number} + * @default 1 + */ + this.resolution = options.resolution; + + /** + * Whether the render view is transparent + * + * @member {boolean} + */ + this.transparent = options.transparent; + + /** + * Whether the render view should be resized automatically + * + * @member {boolean} + */ + this.autoResize = options.autoResize || false; + + /** + * Tracks the blend modes useful for this renderer. + * + * @member {object} + */ + this.blendModes = null; + + + /////////////////////////// + // TODO: Combine these! + + /** + * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. + * + * @member {boolean} + */ + this.preserveDrawingBuffer = options.preserveDrawingBuffer; + + /** + * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. + * If the scene is transparent Pixi will use clearRect to clear the canvas every frame. + * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. + * + * @member {boolean} + * @default + */ + this.clearBeforeRender = options.clearBeforeRender; + + + //////////////////////// + + /** + * The background color as a number. + * + * @member {number} + * @private + */ + this._backgroundColor = 0x000000; + + /** + * The background color as an [R, G, B] array. + * + * @member {number[]} + * @private + */ + this._backgroundColorRgb = [0, 0, 0]; + + /** + * The background color as a string. + * + * @member {string} + * @private + */ + this._backgroundColorString = '#000000'; + + this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter +} + +// constructor +SystemRenderer.prototype.constructor = SystemRenderer; +module.exports = SystemRenderer; + +utils.pluginTarget.mixin(SystemRenderer); +utils.eventTarget.mixin(SystemRenderer.prototype); + +Object.defineProperties(SystemRenderer.prototype, { + /** + * The background color to fill if not transparent + * + * @member {number} + * @memberof SystemRenderer# + */ + backgroundColor: + { + get: function () + { + return this._backgroundColor; + }, + set: function (val) + { + this._backgroundColor = val; + this._backgroundColorString = utils.hex2string(val); + utils.hex2rgb(val, this._backgroundColorRgb); + } + } +}); + +/** + * Resizes the canvas view to the specified width and height + * + * @param width {number} the new width of the canvas view + * @param height {number} the new height of the canvas view + */ +SystemRenderer.prototype.resize = function (width, height) { + this.width = width * this.resolution; + this.height = height * this.resolution; + + this.view.width = this.width; + this.view.height = this.height; + + if (this.autoResize) + { + this.view.style.width = this.width / this.resolution + 'px'; + this.view.style.height = this.height / this.resolution + 'px'; + } +}; + +/** + * Removes everything from the renderer and optionally removes the Canvas DOM element. + * + * @param [removeView=false] {boolean} Removes the Canvas element from the DOM. + */ +SystemRenderer.prototype.destroy = function (removeView) { + if (removeView && this.view.parent) + { + this.view.parent.removeChild(this.view); + } + + this.type = CONST.RENDERER_TYPE.UNKNOWN; + + this.width = 0; + this.height = 0; + + this.view = null; + + this.resolution = 0; + + this.transparent = false; + + this.autoResize = false; + + this.blendModes = null; + + this.preserveDrawingBuffer = false; + this.clearBeforeRender = false; + + this._backgroundColor = 0; + this._backgroundColorRgb = null; + this._backgroundColorString = null; + + this.destroyPlugins(); +}; diff --git a/src/core/renderers/canvas/CanvasRenderer.js b/src/core/renderers/canvas/CanvasRenderer.js index f43e637..716cd0e 100644 --- a/src/core/renderers/canvas/CanvasRenderer.js +++ b/src/core/renderers/canvas/CanvasRenderer.js @@ -1,4 +1,5 @@ -var CanvasMaskManager = require('./utils/CanvasMaskManager'), +var SystemRenderer = require('../SystemRenderer'), + CanvasMaskManager = require('./utils/CanvasMaskManager'), utils = require('../../utils'), math = require('../../math'), CONST = require('../../const'); @@ -15,113 +16,20 @@ * @param [options.view] {HTMLCanvasElement} the canvas to use as a view, optional * @param [options.transparent=false] {boolean} If the render view is transparent, default false * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false + * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 - * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or not before the new render pass. + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. */ function CanvasRenderer(width, height, options) { - utils.sayHello('Canvas'); + SystemRenderer.call(this, 'Canvas', width, height, options); - if (options) - { - for (var i in CONST.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') - { - options[i] = CONST.defaultRenderOptions[i]; - } - } - } - else - { - options = CONST.defaultRenderOptions; - } + this.type = CONST.RENDERER_TYPE.CANVAS; /** - * The renderer type. + * The canvas 2d context that everything is drawn with. * - * @member {number} - */ - this.type = CONST.CANVAS_RENDERER; - - /** - * The resolution of the canvas. - * - * @member {number} - */ - this.resolution = options.resolution; - - /** - * This sets if the CanvasRenderer will clear the canvas or not before the new render pass. - * If the scene is NOT transparent Pixi will use a canvas sized fillRect operation every frame to set the canvas background color. - * If the scene is transparent Pixi will use clearRect to clear the canvas every frame. - * Disable this by setting this to false. For example if your game has a canvas filling background image you often don't need this set. - * - * @member {boolean} - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The background color as a number. - * - * @member {number} - * @private - */ - this._backgroundColor = 0x000000; - - /** - * The background color as a string. - * - * @member {string} - * @private - */ - this._backgroundColorString = '#000000'; - - this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter - - /** - * Whether the render view is transparent - * - * @member {boolean} - */ - this.transparent = options.transparent; - - /** - * Whether the render view should be resized automatically - * - * @member {boolean} - */ - this.autoResize = options.autoResize || false; - - /** - * The width of the canvas view - * - * @member {number} - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @member {number} - * @default 600 - */ - this.height = height || 600; - - this.width *= this.resolution; - this.height *= this.resolution; - - /** - * The canvas element that everything is drawn to. - * - * @member {HTMLCanvasElement} - */ - this.view = options.view || document.createElement('canvas'); - - /** - * The canvas 2d context that everything is drawn with * @member {CanvasRenderingContext2D} */ this.context = this.view.getContext('2d', { alpha: this.transparent }); @@ -133,18 +41,9 @@ */ this.refresh = true; - this.view.width = this.width * this.resolution; - this.view.height = this.height * this.resolution; - /** - * Internal var. + * Instance of a CanvasMaskManager, handles masking when using the canvas renderer. * - * @member {number} - */ - this.count = 0; - - /** - * Instance of a CanvasMaskManager, handles masking when using the canvas renderer * @member {CanvasMaskManager} */ this.maskManager = new CanvasMaskManager(); @@ -157,71 +56,68 @@ */ this.roundPixels = false; - this.scaleMode = null; + /** + * Tracks the active scale mode for this renderer. + * + * @member {CONST.SCALE_MODE} + */ + this.currentScaleMode = CONST.scaleModes.DEFAULT; - this.smoothProperty = null; - - if (this.context.imageSmoothingEnabled) - { - this.smoothProperty = 'imageSmoothingEnabled'; - } - else if (this.context.webkitImageSmoothingEnabled) - { - this.smoothProperty = 'webkitImageSmoothingEnabled'; - } - else if (this.context.mozImageSmoothingEnabled) - { - this.smoothProperty = 'mozImageSmoothingEnabled'; - } - else if (this.context.oImageSmoothingEnabled) - { - this.smoothProperty = 'oImageSmoothingEnabled'; - } - else if (this.context.msImageSmoothingEnabled) - { - this.smoothProperty = 'msImageSmoothingEnabled'; - } - + /** + * Tracks the active blend mode for this renderer. + * + * @member {CONST.SCALE_MODE} + */ this.currentBlendMode = CONST.blendModes.NORMAL; - this.blendModes = null; + /** + * The canvas property used to set the canvas smoothing property. + * + * @member {string} + */ + this.smoothProperty = 'imageSmoothingEnabled'; + + if (!this.context.imageSmoothingEnabled) + { + if (this.context.webkitImageSmoothingEnabled) + { + this.smoothProperty = 'webkitImageSmoothingEnabled'; + } + else if (this.context.mozImageSmoothingEnabled) + { + this.smoothProperty = 'mozImageSmoothingEnabled'; + } + else if (this.context.oImageSmoothingEnabled) + { + this.smoothProperty = 'oImageSmoothingEnabled'; + } + else if (this.context.msImageSmoothingEnabled) + { + this.smoothProperty = 'msImageSmoothingEnabled'; + } + } this._mapBlendModes(); /** * This temporary display object used as the parent of the currently being rendered item + * * @member DisplayObject * @private */ - this._tempDisplayObjectParent = {worldTransform:new math.Matrix(), worldAlpha:1}; + this._tempDisplayObjectParent = { + worldTransform: new math.Matrix(), + worldAlpha: 1 + }; this.resize(width, height); } // constructor +CanvasRenderer.prototype = Object.create(SystemRenderer); CanvasRenderer.prototype.constructor = CanvasRenderer; module.exports = CanvasRenderer; -Object.defineProperties(CanvasRenderer.prototype, { - /** - * The background color to fill if not transparent - * - * @member {number} - * @memberof CanvasRenderer# - */ - backgroundColor: { - get: function () - { - return this._backgroundColor; - }, - set: function (val) - { - this._backgroundColor = val; - this._backgroundColorString = utils.hex2string(val); - } - } -}); - /** * Renders the object to this canvas view * @@ -237,7 +133,7 @@ object.parent = cacheParent; - this.context.setTransform(1,0,0,1,0,0); + this.context.setTransform(1, 0, 0, 1, 0, 0); this.context.globalAlpha = 1; @@ -273,35 +169,22 @@ */ CanvasRenderer.prototype.destroy = function (removeView) { - if (removeView && this.view.parent) - { - this.view.parent.removeChild(this.view); - } + // call the base destroy + SystemRenderer.prototype.destroy.call(this, removeView); - this.view = null; this.context = null; + + this.refresh = true; + + this.maskManager.destroy(); this.maskManager = null; -}; -/** - * Resizes the canvas view to the specified width and height - * - * @param width {number} the new width of the canvas view - * @param height {number} the new height of the canvas view - */ -CanvasRenderer.prototype.resize = function (width, height) -{ - this.width = width * this.resolution; - this.height = height * this.resolution; + this.roundPixels = false; - this.view.width = this.width; - this.view.height = this.height; + this.currentScaleMode = 0; + this.currentBlendMode = 0; - if (this.autoResize) - { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } + this.smoothProperty = null; }; /** diff --git a/src/core/renderers/webgl/WebGLRenderer.js b/src/core/renderers/webgl/WebGLRenderer.js index 268ef7b..eaa78df 100644 --- a/src/core/renderers/webgl/WebGLRenderer.js +++ b/src/core/renderers/webgl/WebGLRenderer.js @@ -1,4 +1,5 @@ -var ShaderManager = require('./managers/ShaderManager'), +var SystemRenderer = require('../SystemRenderer'), + ShaderManager = require('./managers/ShaderManager'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), FilterManager = require('./managers/FilterManager'), @@ -25,148 +26,41 @@ * @param [options.transparent=false] {boolean} If the render view is transparent, default false * @param [options.autoResize=false] {boolean} If the render view is automatically resized, default false * @param [options.antialias=false] {boolean} sets antialias (only applicable in chrome at the moment) - * @param [options.preserveDrawingBuffer=false] {boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * @param [options.resolution=1] {number} the resolution of the renderer retina would be 2 + * @param [options.clearBeforeRender=true] {boolean} This sets if the CanvasRenderer will clear the canvas or + * not before the new render pass. + * @param [options.preserveDrawingBuffer=false] {boolean} enables drawing buffer preservation, enable this if + * you need to call toDataUrl on the webgl context. */ function WebGLRenderer(width, height, options) { - utils.sayHello('webGL'); + SystemRenderer.call(this, 'WebGL', width, height, options); - WebGLRenderer._TEMP__ = this; + this.type = CONST.RENDERER_TYPE.WEBGL; - if (options) - { - for (var i in CONST.defaultRenderOptions) - { - if (typeof options[i] === 'undefined') - { - options[i] = CONST.defaultRenderOptions[i]; - } - } - } - else - { - options = CONST.defaultRenderOptions; - } - this.uuid = utils.uuid(); + this._boundUpdateTexture = this.updateTexture.bind(this); + this._boundDestroyTexture = this.destroyTexture.bind(this); + this._boundContextLost = this.handleContextLost.bind(this); + this._boundContextRestored = this.handleContextRestored.bind(this); + + this.view.addEventListener('webglcontextlost', this._boundContextLost, false); + this.view.addEventListener('webglcontextrestored', this._boundContextRestored, false); /** - * @member {number} - */ - this.type = CONST.WEBGL_RENDERER; - - /** - * The resolution of the renderer + * The options passed in to create a new webgl context. * - * @member {number} - * @default 1 - */ - this.resolution = options.resolution; - - // do a catch.. only 1 webGL renderer.. - - /** - * Whether the render view is transparent - * - * @member {boolean} - */ - this.transparent = options.transparent; - - /** - * The background color as a number. - * - * @member {number} - * @private - */ - this._backgroundColor = 0x000000; - - /** - * The background color as an [R, G, B] array. - * - * @member {number[]} - * @private - */ - this._backgroundColorRgb = [0, 0, 0]; - - this.backgroundColor = options.backgroundColor || this._backgroundColor; // run bg color setter - - /** - * Whether the render view should be resized automatically - * - * @member {boolean} - */ - this.autoResize = options.autoResize || false; - - /** - * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. - * - * @member {boolean} - */ - this.preserveDrawingBuffer = options.preserveDrawingBuffer; - - /** - * This sets if the WebGLRenderer will clear the context texture or not before the new render pass. If true: - * If the renderer is NOT transparent, Pixi will clear to alpha (0, 0, 0, 0). - * If the renderer is transparent, Pixi will clear to the target Stage's background color. - * Disable this by setting this to false. For example: if your game has a canvas filling background image, you often don't need this set. - * - * @member {boolean} - * @default - */ - this.clearBeforeRender = options.clearBeforeRender; - - /** - * The width of the canvas view - * - * @member {number} - * @default 800 - */ - this.width = width || 800; - - /** - * The height of the canvas view - * - * @member {number} - * @default 600 - */ - this.height = height || 600; - - /** - * The canvas element that everything is drawn to - * - * @member {HTMLCanvasElement} - */ - this.view = options.view || document.createElement( 'canvas' ); - - // deal with losing context.. - - /** - * @member {Function} - */ - this.contextLostBound = this.handleContextLost.bind(this); - - /** - * @member {Function} - */ - this.contextRestoredBound = this.handleContextRestored.bind(this); - - this.view.addEventListener('webglcontextlost', this.contextLostBound, false); - this.view.addEventListener('webglcontextrestored', this.contextRestoredBound, false); - - /** * @member {object} * @private */ this._contextOptions = { alpha: this.transparent, - antialias: options.antialias, // SPEED UP?? - premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', - stencil:true, + antialias: options.antialias, + premultipliedAlpha: this.transparent && this.transparent !== 'notMultiplied', + stencil: true, preserveDrawingBuffer: options.preserveDrawingBuffer }; - /** * Counter for the number of draws made each frame * @@ -174,26 +68,30 @@ */ this.drawCount = 0; - // time to create the render managers! each one focuses on managing a state in webGL - - - /** - * Deals with managing the shader programs and their attribs + * Deals with managing the shader programs and their attribs. + * * @member {ShaderManager} */ this.shaderManager = new ShaderManager(this); /** - * Manages the masks using the stencil buffer + * Manages the masks using the stencil buffer. + * * @member {MaskManager} */ this.maskManager = new MaskManager(this); + /** + * Manages the stencil buffer. + * + * @member {StencilManager} + */ this.stencilManager = new StencilManager(this); /** - * Manages the filters + * Manages the filters. + * * @member {FilterManager} */ this.filterManager = new FilterManager(this); @@ -205,14 +103,6 @@ */ this.blendModeManager = new BlendModeManager(this); - this.blendModes = null; - - - - this._boundUpdateTexture = this.updateTexture.bind(this); - this._boundDestroyTexture = this.destroyTexture.bind(this); - - this.currentRenderTarget = this.renderTarget; /** @@ -234,35 +124,12 @@ } // constructor +WebGLRenderer.prototype = Object.create(SystemRenderer); WebGLRenderer.prototype.constructor = WebGLRenderer; module.exports = WebGLRenderer; WebGLRenderer.glContextId = 0; -utils.pluginTarget.mixin(WebGLRenderer); -utils.eventTarget.mixin(WebGLRenderer.prototype); - -Object.defineProperties(WebGLRenderer.prototype, { - /** - * The background color to fill if not transparent - * - * @member {number} - * @memberof WebGLRenderer# - */ - backgroundColor: - { - get: function () - { - return this._backgroundColor; - }, - set: function (val) - { - this._backgroundColor = val; - utils.hex2rgb(val, this._backgroundColorRgb); - } - } -}); - /** * * @private @@ -291,7 +158,7 @@ this.emit('context', gl); - // now resize and we are good to go! + // setup the width/height properties and gl viewport this.resize(this.width, this.height); }; @@ -394,17 +261,7 @@ */ WebGLRenderer.prototype.resize = function (width, height) { - this.width = width * this.resolution; - this.height = height * this.resolution; - - this.view.width = this.width; - this.view.height = this.height; - - if (this.autoResize) - { - this.view.style.width = this.width / this.resolution + 'px'; - this.view.style.height = this.height / this.resolution + 'px'; - } + SystemRenderer.prototype.resize.call(this, width, height); this.gl.viewport(0, 0, this.width, this.height); @@ -518,56 +375,34 @@ */ WebGLRenderer.prototype.destroy = function (removeView) { - if (removeView && this.view.parent) - { - this.view.parent.removeChild(this.view); - } - // remove listeners - this.view.removeEventListener('webglcontextlost', this.contextLostBound); - this.view.removeEventListener('webglcontextrestored', this.contextRestoredBound); + this.view.removeEventListener('webglcontextlost', this._boundContextLost); + this.view.removeEventListener('webglcontextrestored', this._boundContextRestored); - // time to create the render managers! each one focuses on managine a state in webGL + // call base destroy + SystemRenderer.prototype.destroy.call(this, removeView); + + this.uuid = 0; + + // destroy the managers this.shaderManager.destroy(); this.maskManager.destroy(); + this.stencilManager.destroy(); this.filterManager.destroy(); - this.destroyPlugins(); - - // this.uuid = utils.uuid(); - // this.type = CONST.WEBGL_RENDERER; - - // this.resolution = options.resolution; - // this.transparent = options.transparent; - - this._backgroundColor = 0x000000; - this._backgroundColorRgb = null; - - // this.backgroundColor = null; - // this.autoResize = options.autoResize || false; - // this.preserveDrawingBuffer = options.preserveDrawingBuffer; - // this.clearBeforeRender = options.clearBeforeRender; - // this.width = width || 800; - // this.height = height || 600; - - this.view = null; - - this.contextLostBound = null; - this.contextRestoredBound = null; - - this._contextOptions = null; - - this.drawCount = 0; - this.shaderManager = null; this.maskManager = null; this.filterManager = null; this.blendModeManager = null; - this.blendModes = null; + this._boundContextLost = null; + this._boundContextRestored = null; + + this._contextOptions = null; + + this.drawCount = 0; this.gl = null; - this.blendModes = null; }; /** diff --git a/src/core/sprites/Sprite.js b/src/core/sprites/Sprite.js index 37761b5..f9d8103 100644 --- a/src/core/sprites/Sprite.js +++ b/src/core/sprites/Sprite.js @@ -343,10 +343,10 @@ renderer.context.globalAlpha = this.worldAlpha; // If smoothingEnabled is supported and we need to change the smoothing property for this texture - if (renderer.smoothProperty && renderer.scaleMode !== this.texture.baseTexture.scaleMode) + if (renderer.smoothProperty && renderer.currentScaleMode !== this.texture.baseTexture.scaleMode) { - renderer.scaleMode = this.texture.baseTexture.scaleMode; - renderer.context[renderer.smoothProperty] = (renderer.scaleMode === CONST.scaleModes.LINEAR); + renderer.currentScaleMode = this.texture.baseTexture.scaleMode; + renderer.context[renderer.smoothProperty] = (renderer.currentScaleMode === CONST.scaleModes.LINEAR); } // If the texture is trimmed we offset by the trim x/y, otherwise we use the frame dimensions