diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 6440d5e..70cd969 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -14,14 +14,30 @@ * @constructor * @param width=0 {Number} the width of the canvas view * @param height=0 {Number} the height of the canvas view - * @param view {HTMLCanvasElement} the canvas to use as a view, optional - * @param transparent=false {Boolean} If the render view is transparent, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * @param preserveDrawingBuffer=false {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * + * @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.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 + * */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.WebGLRenderer = function(width, height, options) { + if(options) + { + for (var i in PIXI.defaultRenderOptions) + { + options[i] = options[i] || PIXI.defaultRenderOptions[i]; + } + } + else + { + options = PIXI.defaultRenderOptions; + } + + if(!PIXI.defaultRenderer) { PIXI.sayHello('webGL'); @@ -30,6 +46,15 @@ this.type = PIXI.WEBGL_RENDERER; + /** + * The resolution of the renderer + * + * @property resolution + * @type Number + * @default 1 + */ + this.resolution = options.resolution; + // do a catch.. only 1 webGL renderer.. /** * Whether the render view is transparent @@ -37,7 +62,7 @@ * @property transparent * @type Boolean */ - this.transparent = !!transparent; + this.transparent = options.transparent; /** * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. @@ -45,7 +70,7 @@ * @property preserveDrawingBuffer * @type Boolean */ - this.preserveDrawingBuffer = preserveDrawingBuffer; + this.preserveDrawingBuffer = options.preserveDrawingBuffer; /** * The width of the canvas view @@ -71,9 +96,7 @@ * @property view * @type HTMLCanvasElement */ - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; + this.view = options.view || document.createElement( 'canvas' ); // deal with losing context.. this.contextLost = this.handleContextLost.bind(this); @@ -82,19 +105,19 @@ this.view.addEventListener('webglcontextlost', this.contextLost, false); this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false); - this.options = { + this.contextOptions = { alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:!!transparent && transparent !== 'notMultiplied', + antialias: options.antialias, // SPEED UP?? + premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', stencil:true, - preserveDrawingBuffer: preserveDrawingBuffer + preserveDrawingBuffer: options.preserveDrawingBuffer }; var gl = null; ['experimental-webgl', 'webgl'].forEach(function(name) { try { - gl = gl || this.view.getContext(name, this.options); + gl = gl || this.view.getContext(name, this.contextOptions); } catch(e) {} }, this); @@ -131,27 +154,23 @@ PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; } - - - this.projection = new PIXI.Point(); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; this.offset = new PIXI.Point(0, 0); - this.resize(this.width, this.height); + this.resize(width, height); + this.contextLost = false; // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites - //this.primitiveBatch = new PIXI.WebGLPrimitiveBatch(gl); // primitive batch renderer this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters this.stencilManager = new PIXI.WebGLStencilManager(gl); this.blendModeManager = new PIXI.WebGLBlendModeManager(gl); + // TODO remove this.renderSession = {}; this.renderSession.gl = this.gl; this.renderSession.drawCount = 0; @@ -159,17 +178,15 @@ this.renderSession.maskManager = this.maskManager; this.renderSession.filterManager = this.filterManager; this.renderSession.blendModeManager = this.blendModeManager; - // this.renderSession.primitiveBatch = this.primitiveBatch; this.renderSession.spriteBatch = this.spriteBatch; this.renderSession.stencilManager = this.stencilManager; this.renderSession.renderer = this; - - gl.useProgram(this.shaderManager.defaultShader.program); + this.renderSession.resolution = this.resolution; gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); }; @@ -211,7 +228,7 @@ if(!stage._interactiveEventsAdded) { stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); + stage.interactionManager.setTarget( this ); } } @@ -233,7 +250,6 @@ gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); } - gl.clear(gl.COLOR_BUFFER_BIT); this.renderDisplayObject( stage, this.projection ); @@ -300,8 +316,6 @@ // start the sprite batch this.spriteBatch.begin(this.renderSession); -// this.primitiveBatch.begin(this.renderSession); - // start the filter manager this.filterManager.begin(this.renderSession, buffer); @@ -310,8 +324,6 @@ // finish the sprite batch this.spriteBatch.end(); - -// this.primitiveBatch.end(); }; /** @@ -325,11 +337,6 @@ { var i = 0; - //TODO break this out into a texture manager... - // for (i = 0; i < PIXI.texturesToUpdate.length; i++) - // PIXI..updateWebGLTexture(PIXI.texturesToUpdate[i], this.gl); - - for (i=0; i < PIXI.Texture.frameUpdates.length; i++) PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]); @@ -374,8 +381,6 @@ */ PIXI.WebGLRenderer.updateTextureFrame = function(texture) { - //texture.updateFrame = false; - // now set the uvs. Figured that the uv data sits with a texture rather than a sprite. // so uv data is stored on the texture itself texture._updateWebGLuvs(); @@ -390,16 +395,20 @@ */ PIXI.WebGLRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + this.view.style.width = width + 'px'; + this.view.style.height = height + 'px'; + + // console.log(this.width / this.resolution) this.gl.viewport(0, 0, this.width, this.height); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; + this.projection.x = this.width / 2 / this.resolution; + this.projection.y = -this.height / 2 / this.resolution; }; /** @@ -508,11 +517,11 @@ //try 'experimental-webgl' try { - this.gl = this.view.getContext('experimental-webgl', this.options); + this.gl = this.view.getContext('experimental-webgl', this.contextOptions); } catch (e) { //try 'webgl' try { - this.gl = this.view.getContext('webgl', this.options); + this.gl = this.view.getContext('webgl', this.contextOptions); } catch (e2) { // fail, not able to get a context throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); @@ -583,7 +592,6 @@ // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager.destroy(); this.spriteBatch.destroy(); - // this.primitiveBatch.destroy(); this.maskManager.destroy(); this.filterManager.destroy(); @@ -593,7 +601,6 @@ this.filterManager = null; this.gl = null; - // this.renderSession = null; }; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 6440d5e..70cd969 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -14,14 +14,30 @@ * @constructor * @param width=0 {Number} the width of the canvas view * @param height=0 {Number} the height of the canvas view - * @param view {HTMLCanvasElement} the canvas to use as a view, optional - * @param transparent=false {Boolean} If the render view is transparent, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * @param preserveDrawingBuffer=false {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * + * @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.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 + * */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.WebGLRenderer = function(width, height, options) { + if(options) + { + for (var i in PIXI.defaultRenderOptions) + { + options[i] = options[i] || PIXI.defaultRenderOptions[i]; + } + } + else + { + options = PIXI.defaultRenderOptions; + } + + if(!PIXI.defaultRenderer) { PIXI.sayHello('webGL'); @@ -30,6 +46,15 @@ this.type = PIXI.WEBGL_RENDERER; + /** + * The resolution of the renderer + * + * @property resolution + * @type Number + * @default 1 + */ + this.resolution = options.resolution; + // do a catch.. only 1 webGL renderer.. /** * Whether the render view is transparent @@ -37,7 +62,7 @@ * @property transparent * @type Boolean */ - this.transparent = !!transparent; + this.transparent = options.transparent; /** * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. @@ -45,7 +70,7 @@ * @property preserveDrawingBuffer * @type Boolean */ - this.preserveDrawingBuffer = preserveDrawingBuffer; + this.preserveDrawingBuffer = options.preserveDrawingBuffer; /** * The width of the canvas view @@ -71,9 +96,7 @@ * @property view * @type HTMLCanvasElement */ - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; + this.view = options.view || document.createElement( 'canvas' ); // deal with losing context.. this.contextLost = this.handleContextLost.bind(this); @@ -82,19 +105,19 @@ this.view.addEventListener('webglcontextlost', this.contextLost, false); this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false); - this.options = { + this.contextOptions = { alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:!!transparent && transparent !== 'notMultiplied', + antialias: options.antialias, // SPEED UP?? + premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', stencil:true, - preserveDrawingBuffer: preserveDrawingBuffer + preserveDrawingBuffer: options.preserveDrawingBuffer }; var gl = null; ['experimental-webgl', 'webgl'].forEach(function(name) { try { - gl = gl || this.view.getContext(name, this.options); + gl = gl || this.view.getContext(name, this.contextOptions); } catch(e) {} }, this); @@ -131,27 +154,23 @@ PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; } - - - this.projection = new PIXI.Point(); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; this.offset = new PIXI.Point(0, 0); - this.resize(this.width, this.height); + this.resize(width, height); + this.contextLost = false; // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites - //this.primitiveBatch = new PIXI.WebGLPrimitiveBatch(gl); // primitive batch renderer this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters this.stencilManager = new PIXI.WebGLStencilManager(gl); this.blendModeManager = new PIXI.WebGLBlendModeManager(gl); + // TODO remove this.renderSession = {}; this.renderSession.gl = this.gl; this.renderSession.drawCount = 0; @@ -159,17 +178,15 @@ this.renderSession.maskManager = this.maskManager; this.renderSession.filterManager = this.filterManager; this.renderSession.blendModeManager = this.blendModeManager; - // this.renderSession.primitiveBatch = this.primitiveBatch; this.renderSession.spriteBatch = this.spriteBatch; this.renderSession.stencilManager = this.stencilManager; this.renderSession.renderer = this; - - gl.useProgram(this.shaderManager.defaultShader.program); + this.renderSession.resolution = this.resolution; gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); }; @@ -211,7 +228,7 @@ if(!stage._interactiveEventsAdded) { stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); + stage.interactionManager.setTarget( this ); } } @@ -233,7 +250,6 @@ gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); } - gl.clear(gl.COLOR_BUFFER_BIT); this.renderDisplayObject( stage, this.projection ); @@ -300,8 +316,6 @@ // start the sprite batch this.spriteBatch.begin(this.renderSession); -// this.primitiveBatch.begin(this.renderSession); - // start the filter manager this.filterManager.begin(this.renderSession, buffer); @@ -310,8 +324,6 @@ // finish the sprite batch this.spriteBatch.end(); - -// this.primitiveBatch.end(); }; /** @@ -325,11 +337,6 @@ { var i = 0; - //TODO break this out into a texture manager... - // for (i = 0; i < PIXI.texturesToUpdate.length; i++) - // PIXI..updateWebGLTexture(PIXI.texturesToUpdate[i], this.gl); - - for (i=0; i < PIXI.Texture.frameUpdates.length; i++) PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]); @@ -374,8 +381,6 @@ */ PIXI.WebGLRenderer.updateTextureFrame = function(texture) { - //texture.updateFrame = false; - // now set the uvs. Figured that the uv data sits with a texture rather than a sprite. // so uv data is stored on the texture itself texture._updateWebGLuvs(); @@ -390,16 +395,20 @@ */ PIXI.WebGLRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + this.view.style.width = width + 'px'; + this.view.style.height = height + 'px'; + + // console.log(this.width / this.resolution) this.gl.viewport(0, 0, this.width, this.height); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; + this.projection.x = this.width / 2 / this.resolution; + this.projection.y = -this.height / 2 / this.resolution; }; /** @@ -508,11 +517,11 @@ //try 'experimental-webgl' try { - this.gl = this.view.getContext('experimental-webgl', this.options); + this.gl = this.view.getContext('experimental-webgl', this.contextOptions); } catch (e) { //try 'webgl' try { - this.gl = this.view.getContext('webgl', this.options); + this.gl = this.view.getContext('webgl', this.contextOptions); } catch (e2) { // fail, not able to get a context throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); @@ -583,7 +592,6 @@ // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager.destroy(); this.spriteBatch.destroy(); - // this.primitiveBatch.destroy(); this.maskManager.destroy(); this.filterManager.destroy(); @@ -593,7 +601,6 @@ this.filterManager = null; this.gl = null; - // this.renderSession = null; }; diff --git a/src/pixi/renderers/webgl/utils/FilterTexture.js b/src/pixi/renderers/webgl/utils/FilterTexture.js index e7af279..9dada23 100644 --- a/src/pixi/renderers/webgl/utils/FilterTexture.js +++ b/src/pixi/renderers/webgl/utils/FilterTexture.js @@ -19,6 +19,7 @@ */ this.gl = gl; + // next time to create a frame buffer and texture this.frameBuffer = gl.createFramebuffer(); this.texture = gl.createTexture(); @@ -73,11 +74,11 @@ var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + // console.log( width, width ) // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); }; /** diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 6440d5e..70cd969 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -14,14 +14,30 @@ * @constructor * @param width=0 {Number} the width of the canvas view * @param height=0 {Number} the height of the canvas view - * @param view {HTMLCanvasElement} the canvas to use as a view, optional - * @param transparent=false {Boolean} If the render view is transparent, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * @param preserveDrawingBuffer=false {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * + * @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.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 + * */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.WebGLRenderer = function(width, height, options) { + if(options) + { + for (var i in PIXI.defaultRenderOptions) + { + options[i] = options[i] || PIXI.defaultRenderOptions[i]; + } + } + else + { + options = PIXI.defaultRenderOptions; + } + + if(!PIXI.defaultRenderer) { PIXI.sayHello('webGL'); @@ -30,6 +46,15 @@ this.type = PIXI.WEBGL_RENDERER; + /** + * The resolution of the renderer + * + * @property resolution + * @type Number + * @default 1 + */ + this.resolution = options.resolution; + // do a catch.. only 1 webGL renderer.. /** * Whether the render view is transparent @@ -37,7 +62,7 @@ * @property transparent * @type Boolean */ - this.transparent = !!transparent; + this.transparent = options.transparent; /** * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. @@ -45,7 +70,7 @@ * @property preserveDrawingBuffer * @type Boolean */ - this.preserveDrawingBuffer = preserveDrawingBuffer; + this.preserveDrawingBuffer = options.preserveDrawingBuffer; /** * The width of the canvas view @@ -71,9 +96,7 @@ * @property view * @type HTMLCanvasElement */ - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; + this.view = options.view || document.createElement( 'canvas' ); // deal with losing context.. this.contextLost = this.handleContextLost.bind(this); @@ -82,19 +105,19 @@ this.view.addEventListener('webglcontextlost', this.contextLost, false); this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false); - this.options = { + this.contextOptions = { alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:!!transparent && transparent !== 'notMultiplied', + antialias: options.antialias, // SPEED UP?? + premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', stencil:true, - preserveDrawingBuffer: preserveDrawingBuffer + preserveDrawingBuffer: options.preserveDrawingBuffer }; var gl = null; ['experimental-webgl', 'webgl'].forEach(function(name) { try { - gl = gl || this.view.getContext(name, this.options); + gl = gl || this.view.getContext(name, this.contextOptions); } catch(e) {} }, this); @@ -131,27 +154,23 @@ PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; } - - - this.projection = new PIXI.Point(); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; this.offset = new PIXI.Point(0, 0); - this.resize(this.width, this.height); + this.resize(width, height); + this.contextLost = false; // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites - //this.primitiveBatch = new PIXI.WebGLPrimitiveBatch(gl); // primitive batch renderer this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters this.stencilManager = new PIXI.WebGLStencilManager(gl); this.blendModeManager = new PIXI.WebGLBlendModeManager(gl); + // TODO remove this.renderSession = {}; this.renderSession.gl = this.gl; this.renderSession.drawCount = 0; @@ -159,17 +178,15 @@ this.renderSession.maskManager = this.maskManager; this.renderSession.filterManager = this.filterManager; this.renderSession.blendModeManager = this.blendModeManager; - // this.renderSession.primitiveBatch = this.primitiveBatch; this.renderSession.spriteBatch = this.spriteBatch; this.renderSession.stencilManager = this.stencilManager; this.renderSession.renderer = this; - - gl.useProgram(this.shaderManager.defaultShader.program); + this.renderSession.resolution = this.resolution; gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); }; @@ -211,7 +228,7 @@ if(!stage._interactiveEventsAdded) { stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); + stage.interactionManager.setTarget( this ); } } @@ -233,7 +250,6 @@ gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); } - gl.clear(gl.COLOR_BUFFER_BIT); this.renderDisplayObject( stage, this.projection ); @@ -300,8 +316,6 @@ // start the sprite batch this.spriteBatch.begin(this.renderSession); -// this.primitiveBatch.begin(this.renderSession); - // start the filter manager this.filterManager.begin(this.renderSession, buffer); @@ -310,8 +324,6 @@ // finish the sprite batch this.spriteBatch.end(); - -// this.primitiveBatch.end(); }; /** @@ -325,11 +337,6 @@ { var i = 0; - //TODO break this out into a texture manager... - // for (i = 0; i < PIXI.texturesToUpdate.length; i++) - // PIXI..updateWebGLTexture(PIXI.texturesToUpdate[i], this.gl); - - for (i=0; i < PIXI.Texture.frameUpdates.length; i++) PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]); @@ -374,8 +381,6 @@ */ PIXI.WebGLRenderer.updateTextureFrame = function(texture) { - //texture.updateFrame = false; - // now set the uvs. Figured that the uv data sits with a texture rather than a sprite. // so uv data is stored on the texture itself texture._updateWebGLuvs(); @@ -390,16 +395,20 @@ */ PIXI.WebGLRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + this.view.style.width = width + 'px'; + this.view.style.height = height + 'px'; + + // console.log(this.width / this.resolution) this.gl.viewport(0, 0, this.width, this.height); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; + this.projection.x = this.width / 2 / this.resolution; + this.projection.y = -this.height / 2 / this.resolution; }; /** @@ -508,11 +517,11 @@ //try 'experimental-webgl' try { - this.gl = this.view.getContext('experimental-webgl', this.options); + this.gl = this.view.getContext('experimental-webgl', this.contextOptions); } catch (e) { //try 'webgl' try { - this.gl = this.view.getContext('webgl', this.options); + this.gl = this.view.getContext('webgl', this.contextOptions); } catch (e2) { // fail, not able to get a context throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); @@ -583,7 +592,6 @@ // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager.destroy(); this.spriteBatch.destroy(); - // this.primitiveBatch.destroy(); this.maskManager.destroy(); this.filterManager.destroy(); @@ -593,7 +601,6 @@ this.filterManager = null; this.gl = null; - // this.renderSession = null; }; diff --git a/src/pixi/renderers/webgl/utils/FilterTexture.js b/src/pixi/renderers/webgl/utils/FilterTexture.js index e7af279..9dada23 100644 --- a/src/pixi/renderers/webgl/utils/FilterTexture.js +++ b/src/pixi/renderers/webgl/utils/FilterTexture.js @@ -19,6 +19,7 @@ */ this.gl = gl; + // next time to create a frame buffer and texture this.frameBuffer = gl.createFramebuffer(); this.texture = gl.createTexture(); @@ -73,11 +74,11 @@ var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + // console.log( width, width ) // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); }; /** diff --git a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js index ac1aca3..e30cd4f 100755 --- a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js +++ b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js @@ -78,6 +78,9 @@ this.setContext(gl); this.dirty = true; + + this.textures = []; + this.blendModes = []; }; /** @@ -140,15 +143,14 @@ PIXI.WebGLSpriteBatch.prototype.render = function(sprite) { var texture = sprite.texture; - - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== sprite.blendMode; - + + //TODO set blend modes.. // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(sprite.blendMode); } // get the uvs for the texture @@ -191,13 +193,15 @@ } var index = this.currentBatchSize * 4 * this.vertSize; + + var resolution = texture.baseTexture.resolution; - var worldTransform = sprite.worldTransform;//.toArray(); + var worldTransform = sprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -242,8 +246,10 @@ verticies[index++] = tint; // increment the batchsize - this.currentBatchSize++; + this.textures[this.currentBatchSize] = sprite.texture.baseTexture; + this.blendModes[this.currentBatchSize] = sprite.blendMode; + this.currentBatchSize++; }; @@ -257,14 +263,13 @@ { var texture = tilingSprite.tilingTexture; - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== tilingSprite.blendMode; - + // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(tilingSprite.blendMode); } // set the textures uvs temporarily @@ -305,8 +310,8 @@ var height = tilingSprite.height; // TODO trim?? - var aX = tilingSprite.anchor.x; // - tilingSprite.texture.trim.x - var aY = tilingSprite.anchor.y; //- tilingSprite.texture.trim.y + var aX = tilingSprite.anchor.x; + var aY = tilingSprite.anchor.y; var w0 = width * (1-aX); var w1 = width * -aX; @@ -315,12 +320,14 @@ var index = this.currentBatchSize * 4 * this.vertSize; + var resolution = texture.baseTexture.resolution; + var worldTransform = tilingSprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -335,7 +342,7 @@ verticies[index++] = tint; // xy - verticies[index++] = a * w0 + c * h1 + tx; + verticies[index++] = (a * w0 + c * h1 + tx); verticies[index++] = d * h1 + b * w0 + ty; // uv verticies[index++] = uvs.x1; @@ -365,6 +372,8 @@ verticies[index++] = tint; // increment the batchs + this.textures[this.currentBatchSize] = texture.baseTexture; + this.blendModes[this.currentBatchSize] = tilingSprite.blendMode; this.currentBatchSize++; }; @@ -381,10 +390,9 @@ if (this.currentBatchSize===0)return; var gl = this.gl; - + this.renderSession.shaderManager.setShader(this.renderSession.shaderManager.defaultShader); - //TODO - im usre this can be done better - will look to tweak this for 1.7.. if(this.dirty) { this.dirty = false; @@ -407,15 +415,6 @@ } - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.currentBaseTexture, gl)); - - // check if a texture is dirty.. - if(this.currentBaseTexture._dirty[gl.id]) - { - PIXI.updateWebGLTexture(this.currentBaseTexture, gl); - } - // upload the verts to the buffer if(this.currentBatchSize > ( this.size * 0.5 ) ) { @@ -424,19 +423,59 @@ else { var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); } - // var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - //gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); - - // now draw those suckas! - gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0); - + var nextTexture, nextBlendMode; + var batchSize = 0; + var start = 0; + + var currentBaseTexture = null; + var currentBlendMode = this.renderSession.blendModeManager.currentBlendMode; + + for (var i = 0, j = this.currentBatchSize; i < j; i++) { + + nextTexture = this.textures[i]; + nextBlendMode = this.blendModes[i]; + + if(currentBaseTexture !== nextTexture || currentBlendMode !== nextBlendMode) + { + this.renderBatch(currentBaseTexture, batchSize, start); + + start = i; + batchSize = 0; + currentBaseTexture = nextTexture; + currentBlendMode = nextBlendMode; + + this.renderSession.blendModeManager.setBlendMode( currentBlendMode ); + } + + batchSize++; + } + + this.renderBatch(currentBaseTexture, batchSize, start); + // then reset the batch! this.currentBatchSize = 0; +}; +PIXI.WebGLSpriteBatch.prototype.renderBatch = function(texture, size, startIndex) +{ + if(size === 0)return; + + var gl = this.gl; + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id] || PIXI.createWebGLTexture(texture, gl)); + + // check if a texture is dirty.. + if(texture._dirty[gl.id]) + { + PIXI.updateWebGLTexture(this.currentBaseTexture, gl); + } + + // now draw those suckas! + gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); + // increment the draw count this.renderSession.drawCount++; }; @@ -478,4 +517,3 @@ this.gl = null; }; - diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 6440d5e..70cd969 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -14,14 +14,30 @@ * @constructor * @param width=0 {Number} the width of the canvas view * @param height=0 {Number} the height of the canvas view - * @param view {HTMLCanvasElement} the canvas to use as a view, optional - * @param transparent=false {Boolean} If the render view is transparent, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * @param preserveDrawingBuffer=false {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * + * @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.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 + * */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.WebGLRenderer = function(width, height, options) { + if(options) + { + for (var i in PIXI.defaultRenderOptions) + { + options[i] = options[i] || PIXI.defaultRenderOptions[i]; + } + } + else + { + options = PIXI.defaultRenderOptions; + } + + if(!PIXI.defaultRenderer) { PIXI.sayHello('webGL'); @@ -30,6 +46,15 @@ this.type = PIXI.WEBGL_RENDERER; + /** + * The resolution of the renderer + * + * @property resolution + * @type Number + * @default 1 + */ + this.resolution = options.resolution; + // do a catch.. only 1 webGL renderer.. /** * Whether the render view is transparent @@ -37,7 +62,7 @@ * @property transparent * @type Boolean */ - this.transparent = !!transparent; + this.transparent = options.transparent; /** * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. @@ -45,7 +70,7 @@ * @property preserveDrawingBuffer * @type Boolean */ - this.preserveDrawingBuffer = preserveDrawingBuffer; + this.preserveDrawingBuffer = options.preserveDrawingBuffer; /** * The width of the canvas view @@ -71,9 +96,7 @@ * @property view * @type HTMLCanvasElement */ - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; + this.view = options.view || document.createElement( 'canvas' ); // deal with losing context.. this.contextLost = this.handleContextLost.bind(this); @@ -82,19 +105,19 @@ this.view.addEventListener('webglcontextlost', this.contextLost, false); this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false); - this.options = { + this.contextOptions = { alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:!!transparent && transparent !== 'notMultiplied', + antialias: options.antialias, // SPEED UP?? + premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', stencil:true, - preserveDrawingBuffer: preserveDrawingBuffer + preserveDrawingBuffer: options.preserveDrawingBuffer }; var gl = null; ['experimental-webgl', 'webgl'].forEach(function(name) { try { - gl = gl || this.view.getContext(name, this.options); + gl = gl || this.view.getContext(name, this.contextOptions); } catch(e) {} }, this); @@ -131,27 +154,23 @@ PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; } - - - this.projection = new PIXI.Point(); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; this.offset = new PIXI.Point(0, 0); - this.resize(this.width, this.height); + this.resize(width, height); + this.contextLost = false; // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites - //this.primitiveBatch = new PIXI.WebGLPrimitiveBatch(gl); // primitive batch renderer this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters this.stencilManager = new PIXI.WebGLStencilManager(gl); this.blendModeManager = new PIXI.WebGLBlendModeManager(gl); + // TODO remove this.renderSession = {}; this.renderSession.gl = this.gl; this.renderSession.drawCount = 0; @@ -159,17 +178,15 @@ this.renderSession.maskManager = this.maskManager; this.renderSession.filterManager = this.filterManager; this.renderSession.blendModeManager = this.blendModeManager; - // this.renderSession.primitiveBatch = this.primitiveBatch; this.renderSession.spriteBatch = this.spriteBatch; this.renderSession.stencilManager = this.stencilManager; this.renderSession.renderer = this; - - gl.useProgram(this.shaderManager.defaultShader.program); + this.renderSession.resolution = this.resolution; gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); }; @@ -211,7 +228,7 @@ if(!stage._interactiveEventsAdded) { stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); + stage.interactionManager.setTarget( this ); } } @@ -233,7 +250,6 @@ gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); } - gl.clear(gl.COLOR_BUFFER_BIT); this.renderDisplayObject( stage, this.projection ); @@ -300,8 +316,6 @@ // start the sprite batch this.spriteBatch.begin(this.renderSession); -// this.primitiveBatch.begin(this.renderSession); - // start the filter manager this.filterManager.begin(this.renderSession, buffer); @@ -310,8 +324,6 @@ // finish the sprite batch this.spriteBatch.end(); - -// this.primitiveBatch.end(); }; /** @@ -325,11 +337,6 @@ { var i = 0; - //TODO break this out into a texture manager... - // for (i = 0; i < PIXI.texturesToUpdate.length; i++) - // PIXI..updateWebGLTexture(PIXI.texturesToUpdate[i], this.gl); - - for (i=0; i < PIXI.Texture.frameUpdates.length; i++) PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]); @@ -374,8 +381,6 @@ */ PIXI.WebGLRenderer.updateTextureFrame = function(texture) { - //texture.updateFrame = false; - // now set the uvs. Figured that the uv data sits with a texture rather than a sprite. // so uv data is stored on the texture itself texture._updateWebGLuvs(); @@ -390,16 +395,20 @@ */ PIXI.WebGLRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + this.view.style.width = width + 'px'; + this.view.style.height = height + 'px'; + + // console.log(this.width / this.resolution) this.gl.viewport(0, 0, this.width, this.height); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; + this.projection.x = this.width / 2 / this.resolution; + this.projection.y = -this.height / 2 / this.resolution; }; /** @@ -508,11 +517,11 @@ //try 'experimental-webgl' try { - this.gl = this.view.getContext('experimental-webgl', this.options); + this.gl = this.view.getContext('experimental-webgl', this.contextOptions); } catch (e) { //try 'webgl' try { - this.gl = this.view.getContext('webgl', this.options); + this.gl = this.view.getContext('webgl', this.contextOptions); } catch (e2) { // fail, not able to get a context throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); @@ -583,7 +592,6 @@ // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager.destroy(); this.spriteBatch.destroy(); - // this.primitiveBatch.destroy(); this.maskManager.destroy(); this.filterManager.destroy(); @@ -593,7 +601,6 @@ this.filterManager = null; this.gl = null; - // this.renderSession = null; }; diff --git a/src/pixi/renderers/webgl/utils/FilterTexture.js b/src/pixi/renderers/webgl/utils/FilterTexture.js index e7af279..9dada23 100644 --- a/src/pixi/renderers/webgl/utils/FilterTexture.js +++ b/src/pixi/renderers/webgl/utils/FilterTexture.js @@ -19,6 +19,7 @@ */ this.gl = gl; + // next time to create a frame buffer and texture this.frameBuffer = gl.createFramebuffer(); this.texture = gl.createTexture(); @@ -73,11 +74,11 @@ var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + // console.log( width, width ) // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); }; /** diff --git a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js index ac1aca3..e30cd4f 100755 --- a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js +++ b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js @@ -78,6 +78,9 @@ this.setContext(gl); this.dirty = true; + + this.textures = []; + this.blendModes = []; }; /** @@ -140,15 +143,14 @@ PIXI.WebGLSpriteBatch.prototype.render = function(sprite) { var texture = sprite.texture; - - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== sprite.blendMode; - + + //TODO set blend modes.. // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(sprite.blendMode); } // get the uvs for the texture @@ -191,13 +193,15 @@ } var index = this.currentBatchSize * 4 * this.vertSize; + + var resolution = texture.baseTexture.resolution; - var worldTransform = sprite.worldTransform;//.toArray(); + var worldTransform = sprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -242,8 +246,10 @@ verticies[index++] = tint; // increment the batchsize - this.currentBatchSize++; + this.textures[this.currentBatchSize] = sprite.texture.baseTexture; + this.blendModes[this.currentBatchSize] = sprite.blendMode; + this.currentBatchSize++; }; @@ -257,14 +263,13 @@ { var texture = tilingSprite.tilingTexture; - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== tilingSprite.blendMode; - + // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(tilingSprite.blendMode); } // set the textures uvs temporarily @@ -305,8 +310,8 @@ var height = tilingSprite.height; // TODO trim?? - var aX = tilingSprite.anchor.x; // - tilingSprite.texture.trim.x - var aY = tilingSprite.anchor.y; //- tilingSprite.texture.trim.y + var aX = tilingSprite.anchor.x; + var aY = tilingSprite.anchor.y; var w0 = width * (1-aX); var w1 = width * -aX; @@ -315,12 +320,14 @@ var index = this.currentBatchSize * 4 * this.vertSize; + var resolution = texture.baseTexture.resolution; + var worldTransform = tilingSprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -335,7 +342,7 @@ verticies[index++] = tint; // xy - verticies[index++] = a * w0 + c * h1 + tx; + verticies[index++] = (a * w0 + c * h1 + tx); verticies[index++] = d * h1 + b * w0 + ty; // uv verticies[index++] = uvs.x1; @@ -365,6 +372,8 @@ verticies[index++] = tint; // increment the batchs + this.textures[this.currentBatchSize] = texture.baseTexture; + this.blendModes[this.currentBatchSize] = tilingSprite.blendMode; this.currentBatchSize++; }; @@ -381,10 +390,9 @@ if (this.currentBatchSize===0)return; var gl = this.gl; - + this.renderSession.shaderManager.setShader(this.renderSession.shaderManager.defaultShader); - //TODO - im usre this can be done better - will look to tweak this for 1.7.. if(this.dirty) { this.dirty = false; @@ -407,15 +415,6 @@ } - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.currentBaseTexture, gl)); - - // check if a texture is dirty.. - if(this.currentBaseTexture._dirty[gl.id]) - { - PIXI.updateWebGLTexture(this.currentBaseTexture, gl); - } - // upload the verts to the buffer if(this.currentBatchSize > ( this.size * 0.5 ) ) { @@ -424,19 +423,59 @@ else { var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); } - // var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - //gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); - - // now draw those suckas! - gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0); - + var nextTexture, nextBlendMode; + var batchSize = 0; + var start = 0; + + var currentBaseTexture = null; + var currentBlendMode = this.renderSession.blendModeManager.currentBlendMode; + + for (var i = 0, j = this.currentBatchSize; i < j; i++) { + + nextTexture = this.textures[i]; + nextBlendMode = this.blendModes[i]; + + if(currentBaseTexture !== nextTexture || currentBlendMode !== nextBlendMode) + { + this.renderBatch(currentBaseTexture, batchSize, start); + + start = i; + batchSize = 0; + currentBaseTexture = nextTexture; + currentBlendMode = nextBlendMode; + + this.renderSession.blendModeManager.setBlendMode( currentBlendMode ); + } + + batchSize++; + } + + this.renderBatch(currentBaseTexture, batchSize, start); + // then reset the batch! this.currentBatchSize = 0; +}; +PIXI.WebGLSpriteBatch.prototype.renderBatch = function(texture, size, startIndex) +{ + if(size === 0)return; + + var gl = this.gl; + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id] || PIXI.createWebGLTexture(texture, gl)); + + // check if a texture is dirty.. + if(texture._dirty[gl.id]) + { + PIXI.updateWebGLTexture(this.currentBaseTexture, gl); + } + + // now draw those suckas! + gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); + // increment the draw count this.renderSession.drawCount++; }; @@ -478,4 +517,3 @@ this.gl = null; }; - diff --git a/src/pixi/text/Text.js b/src/pixi/text/Text.js index 2b2e26a..3f94b5d 100644 --- a/src/pixi/text/Text.js +++ b/src/pixi/text/Text.js @@ -42,10 +42,16 @@ */ this.context = this.canvas.getContext('2d'); + + this.resolution = 1; + + PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); this.setText(text); this.setStyle(style); + + }; // constructor @@ -160,6 +166,8 @@ */ PIXI.Text.prototype.updateText = function() { + this.texture.baseTexture.resolution = this.resolution; + this.context.font = this.style.font; var outputText = this.text; @@ -184,14 +192,16 @@ var width = maxLineWidth + this.style.strokeThickness; if(this.style.dropShadow)width += this.style.dropShadowDistance; - this.canvas.width = width + this.context.lineWidth; + this.canvas.width = ( width + this.context.lineWidth ) * this.resolution; //calculate text height var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness; var height = lineHeight * lines.length; if(this.style.dropShadow)height += this.style.dropShadowDistance; - this.canvas.height = height; + this.canvas.height = height * this.resolution; + + this.context.scale( this.resolution, this.resolution); if(navigator.isCocoonJS) this.context.clearRect(0,0,this.canvas.width,this.canvas.height); @@ -203,6 +213,7 @@ var linePositionX; var linePositionY; + if(this.style.dropShadow) { this.context.fillStyle = this.style.dropShadowColor; @@ -284,7 +295,6 @@ this._width = this.canvas.width; this._height = this.canvas.height; - this.requiresUpdate = true; }; /** @@ -296,30 +306,38 @@ */ PIXI.Text.prototype._renderWebGL = function(renderSession) { - if(this.requiresUpdate) + if(this.dirty) { - this.requiresUpdate = false; + this.resolution = renderSession.resolution; + + this.updateText(); + this.dirty = false; + PIXI.updateWebGLTexture(this.texture.baseTexture, renderSession.gl); } PIXI.Sprite.prototype._renderWebGL.call(this, renderSession); }; + /** - * Updates the transform of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() +* Renders the object using the WebGL renderer +* +* @method _renderWebGL +* @param renderSession {RenderSession} +* @private +*/ +PIXI.Text.prototype._renderCanvas = function(renderSession) { if(this.dirty) { + this.resolution = renderSession.resolution; + this.updateText(); this.dirty = false; } - - PIXI.Sprite.prototype.updateTransform.call(this); + + PIXI.Sprite.prototype._renderCanvas.call(this, renderSession); }; /* diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 6440d5e..70cd969 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -14,14 +14,30 @@ * @constructor * @param width=0 {Number} the width of the canvas view * @param height=0 {Number} the height of the canvas view - * @param view {HTMLCanvasElement} the canvas to use as a view, optional - * @param transparent=false {Boolean} If the render view is transparent, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * @param preserveDrawingBuffer=false {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * + * @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.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 + * */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.WebGLRenderer = function(width, height, options) { + if(options) + { + for (var i in PIXI.defaultRenderOptions) + { + options[i] = options[i] || PIXI.defaultRenderOptions[i]; + } + } + else + { + options = PIXI.defaultRenderOptions; + } + + if(!PIXI.defaultRenderer) { PIXI.sayHello('webGL'); @@ -30,6 +46,15 @@ this.type = PIXI.WEBGL_RENDERER; + /** + * The resolution of the renderer + * + * @property resolution + * @type Number + * @default 1 + */ + this.resolution = options.resolution; + // do a catch.. only 1 webGL renderer.. /** * Whether the render view is transparent @@ -37,7 +62,7 @@ * @property transparent * @type Boolean */ - this.transparent = !!transparent; + this.transparent = options.transparent; /** * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. @@ -45,7 +70,7 @@ * @property preserveDrawingBuffer * @type Boolean */ - this.preserveDrawingBuffer = preserveDrawingBuffer; + this.preserveDrawingBuffer = options.preserveDrawingBuffer; /** * The width of the canvas view @@ -71,9 +96,7 @@ * @property view * @type HTMLCanvasElement */ - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; + this.view = options.view || document.createElement( 'canvas' ); // deal with losing context.. this.contextLost = this.handleContextLost.bind(this); @@ -82,19 +105,19 @@ this.view.addEventListener('webglcontextlost', this.contextLost, false); this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false); - this.options = { + this.contextOptions = { alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:!!transparent && transparent !== 'notMultiplied', + antialias: options.antialias, // SPEED UP?? + premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', stencil:true, - preserveDrawingBuffer: preserveDrawingBuffer + preserveDrawingBuffer: options.preserveDrawingBuffer }; var gl = null; ['experimental-webgl', 'webgl'].forEach(function(name) { try { - gl = gl || this.view.getContext(name, this.options); + gl = gl || this.view.getContext(name, this.contextOptions); } catch(e) {} }, this); @@ -131,27 +154,23 @@ PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; } - - - this.projection = new PIXI.Point(); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; this.offset = new PIXI.Point(0, 0); - this.resize(this.width, this.height); + this.resize(width, height); + this.contextLost = false; // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites - //this.primitiveBatch = new PIXI.WebGLPrimitiveBatch(gl); // primitive batch renderer this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters this.stencilManager = new PIXI.WebGLStencilManager(gl); this.blendModeManager = new PIXI.WebGLBlendModeManager(gl); + // TODO remove this.renderSession = {}; this.renderSession.gl = this.gl; this.renderSession.drawCount = 0; @@ -159,17 +178,15 @@ this.renderSession.maskManager = this.maskManager; this.renderSession.filterManager = this.filterManager; this.renderSession.blendModeManager = this.blendModeManager; - // this.renderSession.primitiveBatch = this.primitiveBatch; this.renderSession.spriteBatch = this.spriteBatch; this.renderSession.stencilManager = this.stencilManager; this.renderSession.renderer = this; - - gl.useProgram(this.shaderManager.defaultShader.program); + this.renderSession.resolution = this.resolution; gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); }; @@ -211,7 +228,7 @@ if(!stage._interactiveEventsAdded) { stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); + stage.interactionManager.setTarget( this ); } } @@ -233,7 +250,6 @@ gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); } - gl.clear(gl.COLOR_BUFFER_BIT); this.renderDisplayObject( stage, this.projection ); @@ -300,8 +316,6 @@ // start the sprite batch this.spriteBatch.begin(this.renderSession); -// this.primitiveBatch.begin(this.renderSession); - // start the filter manager this.filterManager.begin(this.renderSession, buffer); @@ -310,8 +324,6 @@ // finish the sprite batch this.spriteBatch.end(); - -// this.primitiveBatch.end(); }; /** @@ -325,11 +337,6 @@ { var i = 0; - //TODO break this out into a texture manager... - // for (i = 0; i < PIXI.texturesToUpdate.length; i++) - // PIXI..updateWebGLTexture(PIXI.texturesToUpdate[i], this.gl); - - for (i=0; i < PIXI.Texture.frameUpdates.length; i++) PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]); @@ -374,8 +381,6 @@ */ PIXI.WebGLRenderer.updateTextureFrame = function(texture) { - //texture.updateFrame = false; - // now set the uvs. Figured that the uv data sits with a texture rather than a sprite. // so uv data is stored on the texture itself texture._updateWebGLuvs(); @@ -390,16 +395,20 @@ */ PIXI.WebGLRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + this.view.style.width = width + 'px'; + this.view.style.height = height + 'px'; + + // console.log(this.width / this.resolution) this.gl.viewport(0, 0, this.width, this.height); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; + this.projection.x = this.width / 2 / this.resolution; + this.projection.y = -this.height / 2 / this.resolution; }; /** @@ -508,11 +517,11 @@ //try 'experimental-webgl' try { - this.gl = this.view.getContext('experimental-webgl', this.options); + this.gl = this.view.getContext('experimental-webgl', this.contextOptions); } catch (e) { //try 'webgl' try { - this.gl = this.view.getContext('webgl', this.options); + this.gl = this.view.getContext('webgl', this.contextOptions); } catch (e2) { // fail, not able to get a context throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); @@ -583,7 +592,6 @@ // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager.destroy(); this.spriteBatch.destroy(); - // this.primitiveBatch.destroy(); this.maskManager.destroy(); this.filterManager.destroy(); @@ -593,7 +601,6 @@ this.filterManager = null; this.gl = null; - // this.renderSession = null; }; diff --git a/src/pixi/renderers/webgl/utils/FilterTexture.js b/src/pixi/renderers/webgl/utils/FilterTexture.js index e7af279..9dada23 100644 --- a/src/pixi/renderers/webgl/utils/FilterTexture.js +++ b/src/pixi/renderers/webgl/utils/FilterTexture.js @@ -19,6 +19,7 @@ */ this.gl = gl; + // next time to create a frame buffer and texture this.frameBuffer = gl.createFramebuffer(); this.texture = gl.createTexture(); @@ -73,11 +74,11 @@ var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + // console.log( width, width ) // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); }; /** diff --git a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js index ac1aca3..e30cd4f 100755 --- a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js +++ b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js @@ -78,6 +78,9 @@ this.setContext(gl); this.dirty = true; + + this.textures = []; + this.blendModes = []; }; /** @@ -140,15 +143,14 @@ PIXI.WebGLSpriteBatch.prototype.render = function(sprite) { var texture = sprite.texture; - - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== sprite.blendMode; - + + //TODO set blend modes.. // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(sprite.blendMode); } // get the uvs for the texture @@ -191,13 +193,15 @@ } var index = this.currentBatchSize * 4 * this.vertSize; + + var resolution = texture.baseTexture.resolution; - var worldTransform = sprite.worldTransform;//.toArray(); + var worldTransform = sprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -242,8 +246,10 @@ verticies[index++] = tint; // increment the batchsize - this.currentBatchSize++; + this.textures[this.currentBatchSize] = sprite.texture.baseTexture; + this.blendModes[this.currentBatchSize] = sprite.blendMode; + this.currentBatchSize++; }; @@ -257,14 +263,13 @@ { var texture = tilingSprite.tilingTexture; - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== tilingSprite.blendMode; - + // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(tilingSprite.blendMode); } // set the textures uvs temporarily @@ -305,8 +310,8 @@ var height = tilingSprite.height; // TODO trim?? - var aX = tilingSprite.anchor.x; // - tilingSprite.texture.trim.x - var aY = tilingSprite.anchor.y; //- tilingSprite.texture.trim.y + var aX = tilingSprite.anchor.x; + var aY = tilingSprite.anchor.y; var w0 = width * (1-aX); var w1 = width * -aX; @@ -315,12 +320,14 @@ var index = this.currentBatchSize * 4 * this.vertSize; + var resolution = texture.baseTexture.resolution; + var worldTransform = tilingSprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -335,7 +342,7 @@ verticies[index++] = tint; // xy - verticies[index++] = a * w0 + c * h1 + tx; + verticies[index++] = (a * w0 + c * h1 + tx); verticies[index++] = d * h1 + b * w0 + ty; // uv verticies[index++] = uvs.x1; @@ -365,6 +372,8 @@ verticies[index++] = tint; // increment the batchs + this.textures[this.currentBatchSize] = texture.baseTexture; + this.blendModes[this.currentBatchSize] = tilingSprite.blendMode; this.currentBatchSize++; }; @@ -381,10 +390,9 @@ if (this.currentBatchSize===0)return; var gl = this.gl; - + this.renderSession.shaderManager.setShader(this.renderSession.shaderManager.defaultShader); - //TODO - im usre this can be done better - will look to tweak this for 1.7.. if(this.dirty) { this.dirty = false; @@ -407,15 +415,6 @@ } - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.currentBaseTexture, gl)); - - // check if a texture is dirty.. - if(this.currentBaseTexture._dirty[gl.id]) - { - PIXI.updateWebGLTexture(this.currentBaseTexture, gl); - } - // upload the verts to the buffer if(this.currentBatchSize > ( this.size * 0.5 ) ) { @@ -424,19 +423,59 @@ else { var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); } - // var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - //gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); - - // now draw those suckas! - gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0); - + var nextTexture, nextBlendMode; + var batchSize = 0; + var start = 0; + + var currentBaseTexture = null; + var currentBlendMode = this.renderSession.blendModeManager.currentBlendMode; + + for (var i = 0, j = this.currentBatchSize; i < j; i++) { + + nextTexture = this.textures[i]; + nextBlendMode = this.blendModes[i]; + + if(currentBaseTexture !== nextTexture || currentBlendMode !== nextBlendMode) + { + this.renderBatch(currentBaseTexture, batchSize, start); + + start = i; + batchSize = 0; + currentBaseTexture = nextTexture; + currentBlendMode = nextBlendMode; + + this.renderSession.blendModeManager.setBlendMode( currentBlendMode ); + } + + batchSize++; + } + + this.renderBatch(currentBaseTexture, batchSize, start); + // then reset the batch! this.currentBatchSize = 0; +}; +PIXI.WebGLSpriteBatch.prototype.renderBatch = function(texture, size, startIndex) +{ + if(size === 0)return; + + var gl = this.gl; + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id] || PIXI.createWebGLTexture(texture, gl)); + + // check if a texture is dirty.. + if(texture._dirty[gl.id]) + { + PIXI.updateWebGLTexture(this.currentBaseTexture, gl); + } + + // now draw those suckas! + gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); + // increment the draw count this.renderSession.drawCount++; }; @@ -478,4 +517,3 @@ this.gl = null; }; - diff --git a/src/pixi/text/Text.js b/src/pixi/text/Text.js index 2b2e26a..3f94b5d 100644 --- a/src/pixi/text/Text.js +++ b/src/pixi/text/Text.js @@ -42,10 +42,16 @@ */ this.context = this.canvas.getContext('2d'); + + this.resolution = 1; + + PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); this.setText(text); this.setStyle(style); + + }; // constructor @@ -160,6 +166,8 @@ */ PIXI.Text.prototype.updateText = function() { + this.texture.baseTexture.resolution = this.resolution; + this.context.font = this.style.font; var outputText = this.text; @@ -184,14 +192,16 @@ var width = maxLineWidth + this.style.strokeThickness; if(this.style.dropShadow)width += this.style.dropShadowDistance; - this.canvas.width = width + this.context.lineWidth; + this.canvas.width = ( width + this.context.lineWidth ) * this.resolution; //calculate text height var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness; var height = lineHeight * lines.length; if(this.style.dropShadow)height += this.style.dropShadowDistance; - this.canvas.height = height; + this.canvas.height = height * this.resolution; + + this.context.scale( this.resolution, this.resolution); if(navigator.isCocoonJS) this.context.clearRect(0,0,this.canvas.width,this.canvas.height); @@ -203,6 +213,7 @@ var linePositionX; var linePositionY; + if(this.style.dropShadow) { this.context.fillStyle = this.style.dropShadowColor; @@ -284,7 +295,6 @@ this._width = this.canvas.width; this._height = this.canvas.height; - this.requiresUpdate = true; }; /** @@ -296,30 +306,38 @@ */ PIXI.Text.prototype._renderWebGL = function(renderSession) { - if(this.requiresUpdate) + if(this.dirty) { - this.requiresUpdate = false; + this.resolution = renderSession.resolution; + + this.updateText(); + this.dirty = false; + PIXI.updateWebGLTexture(this.texture.baseTexture, renderSession.gl); } PIXI.Sprite.prototype._renderWebGL.call(this, renderSession); }; + /** - * Updates the transform of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() +* Renders the object using the WebGL renderer +* +* @method _renderWebGL +* @param renderSession {RenderSession} +* @private +*/ +PIXI.Text.prototype._renderCanvas = function(renderSession) { if(this.dirty) { + this.resolution = renderSession.resolution; + this.updateText(); this.dirty = false; } - - PIXI.Sprite.prototype.updateTransform.call(this); + + PIXI.Sprite.prototype._renderCanvas.call(this, renderSession); }; /* diff --git a/src/pixi/textures/BaseTexture.js b/src/pixi/textures/BaseTexture.js index 7e08fcc..3ab40bf 100644 --- a/src/pixi/textures/BaseTexture.js +++ b/src/pixi/textures/BaseTexture.js @@ -22,6 +22,14 @@ PIXI.EventTarget.call( this ); /** + * The Resolution of the texture. + * + * @property resolution + * @type Number + */ + this.resolution = 1; + + /** * [read-only] The width of the base texture set when the image has loaded * * @property width @@ -76,6 +84,9 @@ */ this.premultipliedAlpha = true; + + + // used for webGL this._glTextures = []; @@ -178,6 +189,7 @@ if(!baseTexture) { + // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 var image = new Image();//document.createElement('img'); @@ -185,10 +197,17 @@ { image.crossOrigin = ''; } + image.src = imageUrl; baseTexture = new PIXI.BaseTexture(image, scaleMode); baseTexture.imageUrl = imageUrl; PIXI.BaseTextureCache[imageUrl] = baseTexture; + + // if there is an @2x at the end of the url we are going to assume its a highres image + if( imageUrl.indexOf(PIXI.RETINA_PREFIX + '.') !== -1) + { + baseTexture.resolution = 2; + } } return baseTexture; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 6440d5e..70cd969 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -14,14 +14,30 @@ * @constructor * @param width=0 {Number} the width of the canvas view * @param height=0 {Number} the height of the canvas view - * @param view {HTMLCanvasElement} the canvas to use as a view, optional - * @param transparent=false {Boolean} If the render view is transparent, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * @param preserveDrawingBuffer=false {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * + * @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.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 + * */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.WebGLRenderer = function(width, height, options) { + if(options) + { + for (var i in PIXI.defaultRenderOptions) + { + options[i] = options[i] || PIXI.defaultRenderOptions[i]; + } + } + else + { + options = PIXI.defaultRenderOptions; + } + + if(!PIXI.defaultRenderer) { PIXI.sayHello('webGL'); @@ -30,6 +46,15 @@ this.type = PIXI.WEBGL_RENDERER; + /** + * The resolution of the renderer + * + * @property resolution + * @type Number + * @default 1 + */ + this.resolution = options.resolution; + // do a catch.. only 1 webGL renderer.. /** * Whether the render view is transparent @@ -37,7 +62,7 @@ * @property transparent * @type Boolean */ - this.transparent = !!transparent; + this.transparent = options.transparent; /** * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. @@ -45,7 +70,7 @@ * @property preserveDrawingBuffer * @type Boolean */ - this.preserveDrawingBuffer = preserveDrawingBuffer; + this.preserveDrawingBuffer = options.preserveDrawingBuffer; /** * The width of the canvas view @@ -71,9 +96,7 @@ * @property view * @type HTMLCanvasElement */ - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; + this.view = options.view || document.createElement( 'canvas' ); // deal with losing context.. this.contextLost = this.handleContextLost.bind(this); @@ -82,19 +105,19 @@ this.view.addEventListener('webglcontextlost', this.contextLost, false); this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false); - this.options = { + this.contextOptions = { alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:!!transparent && transparent !== 'notMultiplied', + antialias: options.antialias, // SPEED UP?? + premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', stencil:true, - preserveDrawingBuffer: preserveDrawingBuffer + preserveDrawingBuffer: options.preserveDrawingBuffer }; var gl = null; ['experimental-webgl', 'webgl'].forEach(function(name) { try { - gl = gl || this.view.getContext(name, this.options); + gl = gl || this.view.getContext(name, this.contextOptions); } catch(e) {} }, this); @@ -131,27 +154,23 @@ PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; } - - - this.projection = new PIXI.Point(); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; this.offset = new PIXI.Point(0, 0); - this.resize(this.width, this.height); + this.resize(width, height); + this.contextLost = false; // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites - //this.primitiveBatch = new PIXI.WebGLPrimitiveBatch(gl); // primitive batch renderer this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters this.stencilManager = new PIXI.WebGLStencilManager(gl); this.blendModeManager = new PIXI.WebGLBlendModeManager(gl); + // TODO remove this.renderSession = {}; this.renderSession.gl = this.gl; this.renderSession.drawCount = 0; @@ -159,17 +178,15 @@ this.renderSession.maskManager = this.maskManager; this.renderSession.filterManager = this.filterManager; this.renderSession.blendModeManager = this.blendModeManager; - // this.renderSession.primitiveBatch = this.primitiveBatch; this.renderSession.spriteBatch = this.spriteBatch; this.renderSession.stencilManager = this.stencilManager; this.renderSession.renderer = this; - - gl.useProgram(this.shaderManager.defaultShader.program); + this.renderSession.resolution = this.resolution; gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); }; @@ -211,7 +228,7 @@ if(!stage._interactiveEventsAdded) { stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); + stage.interactionManager.setTarget( this ); } } @@ -233,7 +250,6 @@ gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); } - gl.clear(gl.COLOR_BUFFER_BIT); this.renderDisplayObject( stage, this.projection ); @@ -300,8 +316,6 @@ // start the sprite batch this.spriteBatch.begin(this.renderSession); -// this.primitiveBatch.begin(this.renderSession); - // start the filter manager this.filterManager.begin(this.renderSession, buffer); @@ -310,8 +324,6 @@ // finish the sprite batch this.spriteBatch.end(); - -// this.primitiveBatch.end(); }; /** @@ -325,11 +337,6 @@ { var i = 0; - //TODO break this out into a texture manager... - // for (i = 0; i < PIXI.texturesToUpdate.length; i++) - // PIXI..updateWebGLTexture(PIXI.texturesToUpdate[i], this.gl); - - for (i=0; i < PIXI.Texture.frameUpdates.length; i++) PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]); @@ -374,8 +381,6 @@ */ PIXI.WebGLRenderer.updateTextureFrame = function(texture) { - //texture.updateFrame = false; - // now set the uvs. Figured that the uv data sits with a texture rather than a sprite. // so uv data is stored on the texture itself texture._updateWebGLuvs(); @@ -390,16 +395,20 @@ */ PIXI.WebGLRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + this.view.style.width = width + 'px'; + this.view.style.height = height + 'px'; + + // console.log(this.width / this.resolution) this.gl.viewport(0, 0, this.width, this.height); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; + this.projection.x = this.width / 2 / this.resolution; + this.projection.y = -this.height / 2 / this.resolution; }; /** @@ -508,11 +517,11 @@ //try 'experimental-webgl' try { - this.gl = this.view.getContext('experimental-webgl', this.options); + this.gl = this.view.getContext('experimental-webgl', this.contextOptions); } catch (e) { //try 'webgl' try { - this.gl = this.view.getContext('webgl', this.options); + this.gl = this.view.getContext('webgl', this.contextOptions); } catch (e2) { // fail, not able to get a context throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); @@ -583,7 +592,6 @@ // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager.destroy(); this.spriteBatch.destroy(); - // this.primitiveBatch.destroy(); this.maskManager.destroy(); this.filterManager.destroy(); @@ -593,7 +601,6 @@ this.filterManager = null; this.gl = null; - // this.renderSession = null; }; diff --git a/src/pixi/renderers/webgl/utils/FilterTexture.js b/src/pixi/renderers/webgl/utils/FilterTexture.js index e7af279..9dada23 100644 --- a/src/pixi/renderers/webgl/utils/FilterTexture.js +++ b/src/pixi/renderers/webgl/utils/FilterTexture.js @@ -19,6 +19,7 @@ */ this.gl = gl; + // next time to create a frame buffer and texture this.frameBuffer = gl.createFramebuffer(); this.texture = gl.createTexture(); @@ -73,11 +74,11 @@ var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + // console.log( width, width ) // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); }; /** diff --git a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js index ac1aca3..e30cd4f 100755 --- a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js +++ b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js @@ -78,6 +78,9 @@ this.setContext(gl); this.dirty = true; + + this.textures = []; + this.blendModes = []; }; /** @@ -140,15 +143,14 @@ PIXI.WebGLSpriteBatch.prototype.render = function(sprite) { var texture = sprite.texture; - - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== sprite.blendMode; - + + //TODO set blend modes.. // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(sprite.blendMode); } // get the uvs for the texture @@ -191,13 +193,15 @@ } var index = this.currentBatchSize * 4 * this.vertSize; + + var resolution = texture.baseTexture.resolution; - var worldTransform = sprite.worldTransform;//.toArray(); + var worldTransform = sprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -242,8 +246,10 @@ verticies[index++] = tint; // increment the batchsize - this.currentBatchSize++; + this.textures[this.currentBatchSize] = sprite.texture.baseTexture; + this.blendModes[this.currentBatchSize] = sprite.blendMode; + this.currentBatchSize++; }; @@ -257,14 +263,13 @@ { var texture = tilingSprite.tilingTexture; - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== tilingSprite.blendMode; - + // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(tilingSprite.blendMode); } // set the textures uvs temporarily @@ -305,8 +310,8 @@ var height = tilingSprite.height; // TODO trim?? - var aX = tilingSprite.anchor.x; // - tilingSprite.texture.trim.x - var aY = tilingSprite.anchor.y; //- tilingSprite.texture.trim.y + var aX = tilingSprite.anchor.x; + var aY = tilingSprite.anchor.y; var w0 = width * (1-aX); var w1 = width * -aX; @@ -315,12 +320,14 @@ var index = this.currentBatchSize * 4 * this.vertSize; + var resolution = texture.baseTexture.resolution; + var worldTransform = tilingSprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -335,7 +342,7 @@ verticies[index++] = tint; // xy - verticies[index++] = a * w0 + c * h1 + tx; + verticies[index++] = (a * w0 + c * h1 + tx); verticies[index++] = d * h1 + b * w0 + ty; // uv verticies[index++] = uvs.x1; @@ -365,6 +372,8 @@ verticies[index++] = tint; // increment the batchs + this.textures[this.currentBatchSize] = texture.baseTexture; + this.blendModes[this.currentBatchSize] = tilingSprite.blendMode; this.currentBatchSize++; }; @@ -381,10 +390,9 @@ if (this.currentBatchSize===0)return; var gl = this.gl; - + this.renderSession.shaderManager.setShader(this.renderSession.shaderManager.defaultShader); - //TODO - im usre this can be done better - will look to tweak this for 1.7.. if(this.dirty) { this.dirty = false; @@ -407,15 +415,6 @@ } - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.currentBaseTexture, gl)); - - // check if a texture is dirty.. - if(this.currentBaseTexture._dirty[gl.id]) - { - PIXI.updateWebGLTexture(this.currentBaseTexture, gl); - } - // upload the verts to the buffer if(this.currentBatchSize > ( this.size * 0.5 ) ) { @@ -424,19 +423,59 @@ else { var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); } - // var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - //gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); - - // now draw those suckas! - gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0); - + var nextTexture, nextBlendMode; + var batchSize = 0; + var start = 0; + + var currentBaseTexture = null; + var currentBlendMode = this.renderSession.blendModeManager.currentBlendMode; + + for (var i = 0, j = this.currentBatchSize; i < j; i++) { + + nextTexture = this.textures[i]; + nextBlendMode = this.blendModes[i]; + + if(currentBaseTexture !== nextTexture || currentBlendMode !== nextBlendMode) + { + this.renderBatch(currentBaseTexture, batchSize, start); + + start = i; + batchSize = 0; + currentBaseTexture = nextTexture; + currentBlendMode = nextBlendMode; + + this.renderSession.blendModeManager.setBlendMode( currentBlendMode ); + } + + batchSize++; + } + + this.renderBatch(currentBaseTexture, batchSize, start); + // then reset the batch! this.currentBatchSize = 0; +}; +PIXI.WebGLSpriteBatch.prototype.renderBatch = function(texture, size, startIndex) +{ + if(size === 0)return; + + var gl = this.gl; + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id] || PIXI.createWebGLTexture(texture, gl)); + + // check if a texture is dirty.. + if(texture._dirty[gl.id]) + { + PIXI.updateWebGLTexture(this.currentBaseTexture, gl); + } + + // now draw those suckas! + gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); + // increment the draw count this.renderSession.drawCount++; }; @@ -478,4 +517,3 @@ this.gl = null; }; - diff --git a/src/pixi/text/Text.js b/src/pixi/text/Text.js index 2b2e26a..3f94b5d 100644 --- a/src/pixi/text/Text.js +++ b/src/pixi/text/Text.js @@ -42,10 +42,16 @@ */ this.context = this.canvas.getContext('2d'); + + this.resolution = 1; + + PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); this.setText(text); this.setStyle(style); + + }; // constructor @@ -160,6 +166,8 @@ */ PIXI.Text.prototype.updateText = function() { + this.texture.baseTexture.resolution = this.resolution; + this.context.font = this.style.font; var outputText = this.text; @@ -184,14 +192,16 @@ var width = maxLineWidth + this.style.strokeThickness; if(this.style.dropShadow)width += this.style.dropShadowDistance; - this.canvas.width = width + this.context.lineWidth; + this.canvas.width = ( width + this.context.lineWidth ) * this.resolution; //calculate text height var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness; var height = lineHeight * lines.length; if(this.style.dropShadow)height += this.style.dropShadowDistance; - this.canvas.height = height; + this.canvas.height = height * this.resolution; + + this.context.scale( this.resolution, this.resolution); if(navigator.isCocoonJS) this.context.clearRect(0,0,this.canvas.width,this.canvas.height); @@ -203,6 +213,7 @@ var linePositionX; var linePositionY; + if(this.style.dropShadow) { this.context.fillStyle = this.style.dropShadowColor; @@ -284,7 +295,6 @@ this._width = this.canvas.width; this._height = this.canvas.height; - this.requiresUpdate = true; }; /** @@ -296,30 +306,38 @@ */ PIXI.Text.prototype._renderWebGL = function(renderSession) { - if(this.requiresUpdate) + if(this.dirty) { - this.requiresUpdate = false; + this.resolution = renderSession.resolution; + + this.updateText(); + this.dirty = false; + PIXI.updateWebGLTexture(this.texture.baseTexture, renderSession.gl); } PIXI.Sprite.prototype._renderWebGL.call(this, renderSession); }; + /** - * Updates the transform of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() +* Renders the object using the WebGL renderer +* +* @method _renderWebGL +* @param renderSession {RenderSession} +* @private +*/ +PIXI.Text.prototype._renderCanvas = function(renderSession) { if(this.dirty) { + this.resolution = renderSession.resolution; + this.updateText(); this.dirty = false; } - - PIXI.Sprite.prototype.updateTransform.call(this); + + PIXI.Sprite.prototype._renderCanvas.call(this, renderSession); }; /* diff --git a/src/pixi/textures/BaseTexture.js b/src/pixi/textures/BaseTexture.js index 7e08fcc..3ab40bf 100644 --- a/src/pixi/textures/BaseTexture.js +++ b/src/pixi/textures/BaseTexture.js @@ -22,6 +22,14 @@ PIXI.EventTarget.call( this ); /** + * The Resolution of the texture. + * + * @property resolution + * @type Number + */ + this.resolution = 1; + + /** * [read-only] The width of the base texture set when the image has loaded * * @property width @@ -76,6 +84,9 @@ */ this.premultipliedAlpha = true; + + + // used for webGL this._glTextures = []; @@ -178,6 +189,7 @@ if(!baseTexture) { + // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 var image = new Image();//document.createElement('img'); @@ -185,10 +197,17 @@ { image.crossOrigin = ''; } + image.src = imageUrl; baseTexture = new PIXI.BaseTexture(image, scaleMode); baseTexture.imageUrl = imageUrl; PIXI.BaseTextureCache[imageUrl] = baseTexture; + + // if there is an @2x at the end of the url we are going to assume its a highres image + if( imageUrl.indexOf(PIXI.RETINA_PREFIX + '.') !== -1) + { + baseTexture.resolution = 2; + } } return baseTexture; diff --git a/src/pixi/textures/RenderTexture.js b/src/pixi/textures/RenderTexture.js index 82a37f5..f1e4ad1 100644 --- a/src/pixi/textures/RenderTexture.js +++ b/src/pixi/textures/RenderTexture.js @@ -30,8 +30,9 @@ * @param width {Number} The width of the render texture * @param height {Number} The height of the render texture * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @param resolution {Number} The resolution of the texture being generated */ -PIXI.RenderTexture = function(width, height, renderer, scaleMode) +PIXI.RenderTexture = function(width, height, renderer, scaleMode, resolution) { PIXI.EventTarget.call( this ); @@ -50,6 +51,14 @@ * @type Number */ this.height = height || 100; + + /** + * The Resolution of the texture. + * + * @property resolution + * @type Number + */ + this.resolution = resolution || 1; /** * The framing rectangle of the render texture @@ -57,7 +66,7 @@ * @property frame * @type Rectangle */ - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + this.frame = new PIXI.Rectangle(0, 0, this.width * this.resolution, this.height * this.resolution); /** * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering, @@ -66,8 +75,9 @@ * @property crop * @type Rectangle */ - this.crop = new PIXI.Rectangle(0, 0, this.width, this.height); - + this.crop = new PIXI.Rectangle(0, 0, this.width * this.resolution, this.height * this.resolution); + + /** * The base texture object that this texture uses * @@ -75,10 +85,12 @@ * @type BaseTexture */ this.baseTexture = new PIXI.BaseTexture(); - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; + this.baseTexture.width = this.width * this.resolution; + this.baseTexture.height = this.height * this.resolution; this.baseTexture._glTextures = []; + this.baseTexture.resolution = this.resolution; + this.baseTexture.scaleMode = scaleMode || PIXI.scaleModes.DEFAULT; this.baseTexture.hasLoaded = true; @@ -90,16 +102,16 @@ { var gl = this.renderer.gl; - this.textureBuffer = new PIXI.FilterTexture(gl, this.width, this.height, this.baseTexture.scaleMode); + this.textureBuffer = new PIXI.FilterTexture(gl, this.width * this.resolution, this.height * this.resolution, this.baseTexture.scaleMode); this.baseTexture._glTextures[gl.id] = this.textureBuffer.texture; this.render = this.renderWebGL; - this.projection = new PIXI.Point(this.width/2 , -this.height/2); + this.projection = new PIXI.Point(this.width*0.5, -this.height*0.5); } else { this.render = this.renderCanvas; - this.textureBuffer = new PIXI.CanvasBuffer(this.width, this.height); + this.textureBuffer = new PIXI.CanvasBuffer(this.width* this.resolution, this.height* this.resolution); this.baseTexture.source = this.textureBuffer.canvas; } @@ -146,7 +158,7 @@ } if(!this.valid)return; - this.textureBuffer.resize(this.width, this.height); + this.textureBuffer.resize(this.width * this.resolution, this.height * this.resolution); }; @@ -183,7 +195,7 @@ gl.colorMask(true, true, true, true); - gl.viewport(0, 0, this.width, this.height); + gl.viewport(0, 0, this.width * this.resolution, this.height * this.resolution); gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer ); @@ -254,6 +266,9 @@ displayObject.worldTransform.ty = 0; } + // displayObject.worldTransform.a = 0.5; + // displayObject.worldTransform.d = 0.5; + for(var i = 0, j = children.length; i < j; i++) { children[i].updateTransform(); @@ -263,8 +278,15 @@ var context = this.textureBuffer.context; - this.renderer.renderDisplayObject(displayObject, context); + var realResolution = this.renderer.resolution; + this.renderer.resolution = this.resolution; + //this.baseTexture.resolution = 2; + + this.renderer.renderDisplayObject(displayObject, context); + + this.renderer.resolution = realResolution; + context.setTransform(1,0,0,1,0,0); displayObject.worldTransform = originalWorldTransform; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 3998b67..bf596cc 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -100,6 +100,8 @@ * */ this.mouseOut = false; + + this.resolution = 1; }; // constructor @@ -158,6 +160,7 @@ PIXI.InteractionManager.prototype.setTarget = function(target) { this.target = target; + this.resolution = target.resolution; //check if the dom element has been set. If it has don't do anything if( this.interactionDOMElement === null ) { @@ -340,8 +343,8 @@ // TODO optimize by not check EVERY TIME! maybe half as often? // var rect = this.interactionDOMElement.getBoundingClientRect(); - this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width); - this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height); + this.mouse.global.x = (event.clientX - rect.left) * (this.target.width / rect.width) / this.resolution; + this.mouse.global.y = (event.clientY - rect.top) * ( this.target.height / rect.height) / this.resolution; var length = this.interactiveItems.length; @@ -613,8 +616,8 @@ touchData.originalEvent = event || window.event; // update the touch position - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -658,8 +661,8 @@ touchData.originalEvent = event || window.event; this.touchs[touchEvent.identifier] = touchData; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; @@ -714,8 +717,8 @@ var touchEvent = changedTouches[i]; var touchData = this.touchs[touchEvent.identifier]; var up = false; - touchData.global.x = (touchEvent.clientX - rect.left) * (this.target.width / rect.width); - touchData.global.y = (touchEvent.clientY - rect.top) * (this.target.height / rect.height); + touchData.global.x = ( (touchEvent.clientX - rect.left) * (this.target.width / rect.width) ) / this.resolution; + touchData.global.y = ( (touchEvent.clientY - rect.top) * (this.target.height / rect.height) ) / this.resolution; if(navigator.isCocoonJS && !rect.left && !rect.top && !event.target.style.width && !event.target.style.height) { //Support for CocoonJS fullscreen scale modes touchData.global.x = touchEvent.clientX; diff --git a/src/pixi/Pixi.js b/src/pixi/Pixi.js index 8cd965e..3872d0d 100644 --- a/src/pixi/Pixi.js +++ b/src/pixi/Pixi.js @@ -68,9 +68,21 @@ PIXI.RAD_TO_DEG = 180 / Math.PI; PIXI.DEG_TO_RAD = Math.PI / 180; +PIXI.RETINA_PREFIX = "@2x"; +//PIXI.SCALE_PREFIX "@x%%"; PIXI.dontSayHello = false; + +PIXI.defaultRenderOptions = { + view:null, + transparent:false, + antialias:false, + preserveDrawingBuffer:false, + resolution:1, + clearBeforeRender:true +} + PIXI.sayHello = function (type) { if(PIXI.dontSayHello)return; diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index 7416d20..16f74fe 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -47,7 +47,7 @@ */ PIXI.Matrix.prototype.toArray = function(transpose) { - if(!this.array) this.array = new Float32Array(9); + if(!this.array) this.array = new PIXI.Float32Array(9); var array = this.array; if(transpose) @@ -117,6 +117,70 @@ return newPos; }; +/** + * Translates the matrix on the x and y. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.translate = function(x, y) +{ + this.tx += x; + this.ty += y; + + return this; +}; + +/** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally + * @param {Number} y The amount to scale vertically + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.scale = function(x, y) +{ + this.a *= x; + this.d *= y; + this.c *= x; + this.b *= y; + this.tx *= x; + this.ty *= y; + + return this; +}; + + +/** + * Applies a rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle in radians. + * @return {Matrix} This matrix. Good for chaining method calls. + **/ +PIXI.Matrix.prototype.rotate = function(angle) +{ + var cos = Math.cos( angle ); + var sin = Math.sin( angle ); + + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a1 * cos-this.b * sin; + this.b = a1 * sin+this.b * cos; + this.c = c1 * cos-this.d * sin; + this.d = c1 * sin+this.d * cos; + this.tx = tx1 * cos - this.ty * sin; + this.ty = tx1 * sin + this.ty * cos; + + return this; +}; + + + + + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index 4a7b132..a6fcee3 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -520,11 +520,20 @@ if(this._interactive)this.stage.dirty = true; }; -PIXI.DisplayObject.prototype.generateTexture = function(renderer) +/** + * Useful function that returns a texture of the displayObject object that can then be used to create sprites + * This can be quite useful if your displayObject is static / complicated and needs to be reused multiple times. + * + * @method generateTexture + * @param resolution {Number} The resolution of the texture being generated + * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @return {Texture} a texture of the graphics object + */ +PIXI.DisplayObject.prototype.generateTexture = function(resolution, scaleMode, renderer) { var bounds = this.getLocalBounds(); - var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer); + var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0, renderer, scaleMode, resolution); renderTexture.render(this, new PIXI.Point(-bounds.x, -bounds.y) ); return renderTexture; diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 999c774..ce58214 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -126,7 +126,7 @@ } else { - throw new Error(child + ' The index '+ index +' supplied is out of bounds ' + this.children.length); + throw new Error(child + 'addChildAt: The index '+ index +' supplied is out of bounds ' + this.children.length); } }; @@ -170,7 +170,7 @@ } else { - throw new Error('Supplied index does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); + throw new Error('getChildAt: Supplied index '+ index +' does not exist in the child list, or the supplied DisplayObject must be a child of the caller'); } }; @@ -232,7 +232,7 @@ } else { - throw new Error( 'Range Error, numeric values are outside the acceptable range' ); + throw new Error( 'removeChildren: Range Error, numeric values are outside the acceptable range' ); } }; @@ -459,7 +459,7 @@ if(this._mask) { - renderSession.maskManager.pushMask(this._mask, renderSession.context); + renderSession.maskManager.pushMask(this._mask, renderSession); } for(var i=0,j=this.children.length; i 0) - //{ - // PIXI.Texture.frameUpdates.length = 0; - //} + // TODO remove this eventually! + if(PIXI.Texture.frameUpdates.length > 0) + { + PIXI.Texture.frameUpdates.length = 0; + } }; /** @@ -233,11 +258,15 @@ */ PIXI.CanvasRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + + this.view.style.width = this.width / this.resolution + "px"; + this.view.style.height = this.height / this.resolution + "px"; + }; /** @@ -255,6 +284,7 @@ //var context = this.context; this.renderSession.context = context || this.context; + this.renderSession.resolution = this.resolution; displayObject._renderCanvas(this.renderSession); }; diff --git a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js index 82e5f9d..690e976 100644 --- a/src/pixi/renderers/canvas/utils/CanvasMaskManager.js +++ b/src/pixi/renderers/canvas/utils/CanvasMaskManager.js @@ -20,14 +20,23 @@ * @param maskData the maskData that will be pushed * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, context) +PIXI.CanvasMaskManager.prototype.pushMask = function(maskData, renderSession) { + var context = renderSession.context; + context.save(); var cacheAlpha = maskData.alpha; var transform = maskData.worldTransform; - context.setTransform(transform.a, transform.c, transform.b, transform.d, transform.tx, transform.ty); + var resolution = renderSession.resolution; + + context.setTransform(transform.a * resolution, + transform.c * resolution, + transform.b * resolution, + transform.d * resolution, + transform.tx * resolution, + transform.ty * resolution); PIXI.CanvasGraphics.renderGraphicsMask(maskData, context); @@ -42,7 +51,7 @@ * @method popMask * @param context {Context2D} the 2d drawing method of the canvas */ -PIXI.CanvasMaskManager.prototype.popMask = function(context) +PIXI.CanvasMaskManager.prototype.popMask = function(renderSession) { - context.restore(); + renderSession.context.restore(); }; \ No newline at end of file diff --git a/src/pixi/renderers/webgl/WebGLRenderer.js b/src/pixi/renderers/webgl/WebGLRenderer.js index 6440d5e..70cd969 100644 --- a/src/pixi/renderers/webgl/WebGLRenderer.js +++ b/src/pixi/renderers/webgl/WebGLRenderer.js @@ -14,14 +14,30 @@ * @constructor * @param width=0 {Number} the width of the canvas view * @param height=0 {Number} the height of the canvas view - * @param view {HTMLCanvasElement} the canvas to use as a view, optional - * @param transparent=false {Boolean} If the render view is transparent, default false - * @param antialias=false {Boolean} sets antialias (only applicable in chrome at the moment) - * @param preserveDrawingBuffer=false {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context * + * @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.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 + * */ -PIXI.WebGLRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.WebGLRenderer = function(width, height, options) { + if(options) + { + for (var i in PIXI.defaultRenderOptions) + { + options[i] = options[i] || PIXI.defaultRenderOptions[i]; + } + } + else + { + options = PIXI.defaultRenderOptions; + } + + if(!PIXI.defaultRenderer) { PIXI.sayHello('webGL'); @@ -30,6 +46,15 @@ this.type = PIXI.WEBGL_RENDERER; + /** + * The resolution of the renderer + * + * @property resolution + * @type Number + * @default 1 + */ + this.resolution = options.resolution; + // do a catch.. only 1 webGL renderer.. /** * Whether the render view is transparent @@ -37,7 +62,7 @@ * @property transparent * @type Boolean */ - this.transparent = !!transparent; + this.transparent = options.transparent; /** * The value of the preserveDrawingBuffer flag affects whether or not the contents of the stencil buffer is retained after rendering. @@ -45,7 +70,7 @@ * @property preserveDrawingBuffer * @type Boolean */ - this.preserveDrawingBuffer = preserveDrawingBuffer; + this.preserveDrawingBuffer = options.preserveDrawingBuffer; /** * The width of the canvas view @@ -71,9 +96,7 @@ * @property view * @type HTMLCanvasElement */ - this.view = view || document.createElement( 'canvas' ); - this.view.width = this.width; - this.view.height = this.height; + this.view = options.view || document.createElement( 'canvas' ); // deal with losing context.. this.contextLost = this.handleContextLost.bind(this); @@ -82,19 +105,19 @@ this.view.addEventListener('webglcontextlost', this.contextLost, false); this.view.addEventListener('webglcontextrestored', this.contextRestoredLost, false); - this.options = { + this.contextOptions = { alpha: this.transparent, - antialias:!!antialias, // SPEED UP?? - premultipliedAlpha:!!transparent && transparent !== 'notMultiplied', + antialias: options.antialias, // SPEED UP?? + premultipliedAlpha:this.transparent && this.transparent !== 'notMultiplied', stencil:true, - preserveDrawingBuffer: preserveDrawingBuffer + preserveDrawingBuffer: options.preserveDrawingBuffer }; var gl = null; ['experimental-webgl', 'webgl'].forEach(function(name) { try { - gl = gl || this.view.getContext(name, this.options); + gl = gl || this.view.getContext(name, this.contextOptions); } catch(e) {} }, this); @@ -131,27 +154,23 @@ PIXI.blendModesWebGL[PIXI.blendModes.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; } - - - this.projection = new PIXI.Point(); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; this.offset = new PIXI.Point(0, 0); - this.resize(this.width, this.height); + this.resize(width, height); + this.contextLost = false; // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager = new PIXI.WebGLShaderManager(gl); // deals with managing the shader programs and their attribs this.spriteBatch = new PIXI.WebGLSpriteBatch(gl); // manages the rendering of sprites - //this.primitiveBatch = new PIXI.WebGLPrimitiveBatch(gl); // primitive batch renderer this.maskManager = new PIXI.WebGLMaskManager(gl); // manages the masks using the stencil buffer this.filterManager = new PIXI.WebGLFilterManager(gl, this.transparent); // manages the filters this.stencilManager = new PIXI.WebGLStencilManager(gl); this.blendModeManager = new PIXI.WebGLBlendModeManager(gl); + // TODO remove this.renderSession = {}; this.renderSession.gl = this.gl; this.renderSession.drawCount = 0; @@ -159,17 +178,15 @@ this.renderSession.maskManager = this.maskManager; this.renderSession.filterManager = this.filterManager; this.renderSession.blendModeManager = this.blendModeManager; - // this.renderSession.primitiveBatch = this.primitiveBatch; this.renderSession.spriteBatch = this.spriteBatch; this.renderSession.stencilManager = this.stencilManager; this.renderSession.renderer = this; - - gl.useProgram(this.shaderManager.defaultShader.program); + this.renderSession.resolution = this.resolution; gl.disable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); - gl.enable(gl.BLEND); + gl.colorMask(true, true, true, this.transparent); }; @@ -211,7 +228,7 @@ if(!stage._interactiveEventsAdded) { stage._interactiveEventsAdded = true; - stage.interactionManager.setTarget(this); + stage.interactionManager.setTarget( this ); } } @@ -233,7 +250,6 @@ gl.clearColor(stage.backgroundColorSplit[0],stage.backgroundColorSplit[1],stage.backgroundColorSplit[2], 1); } - gl.clear(gl.COLOR_BUFFER_BIT); this.renderDisplayObject( stage, this.projection ); @@ -300,8 +316,6 @@ // start the sprite batch this.spriteBatch.begin(this.renderSession); -// this.primitiveBatch.begin(this.renderSession); - // start the filter manager this.filterManager.begin(this.renderSession, buffer); @@ -310,8 +324,6 @@ // finish the sprite batch this.spriteBatch.end(); - -// this.primitiveBatch.end(); }; /** @@ -325,11 +337,6 @@ { var i = 0; - //TODO break this out into a texture manager... - // for (i = 0; i < PIXI.texturesToUpdate.length; i++) - // PIXI..updateWebGLTexture(PIXI.texturesToUpdate[i], this.gl); - - for (i=0; i < PIXI.Texture.frameUpdates.length; i++) PIXI.WebGLRenderer.updateTextureFrame(PIXI.Texture.frameUpdates[i]); @@ -374,8 +381,6 @@ */ PIXI.WebGLRenderer.updateTextureFrame = function(texture) { - //texture.updateFrame = false; - // now set the uvs. Figured that the uv data sits with a texture rather than a sprite. // so uv data is stored on the texture itself texture._updateWebGLuvs(); @@ -390,16 +395,20 @@ */ PIXI.WebGLRenderer.prototype.resize = function(width, height) { - this.width = width; - this.height = height; + this.width = width * this.resolution; + this.height = height * this.resolution; - this.view.width = width; - this.view.height = height; + this.view.width = this.width; + this.view.height = this.height; + this.view.style.width = width + 'px'; + this.view.style.height = height + 'px'; + + // console.log(this.width / this.resolution) this.gl.viewport(0, 0, this.width, this.height); - this.projection.x = this.width/2; - this.projection.y = -this.height/2; + this.projection.x = this.width / 2 / this.resolution; + this.projection.y = -this.height / 2 / this.resolution; }; /** @@ -508,11 +517,11 @@ //try 'experimental-webgl' try { - this.gl = this.view.getContext('experimental-webgl', this.options); + this.gl = this.view.getContext('experimental-webgl', this.contextOptions); } catch (e) { //try 'webgl' try { - this.gl = this.view.getContext('webgl', this.options); + this.gl = this.view.getContext('webgl', this.contextOptions); } catch (e2) { // fail, not able to get a context throw new Error(' This browser does not support webGL. Try using the canvas renderer' + this); @@ -583,7 +592,6 @@ // time to create the render managers! each one focuses on managine a state in webGL this.shaderManager.destroy(); this.spriteBatch.destroy(); - // this.primitiveBatch.destroy(); this.maskManager.destroy(); this.filterManager.destroy(); @@ -593,7 +601,6 @@ this.filterManager = null; this.gl = null; - // this.renderSession = null; }; diff --git a/src/pixi/renderers/webgl/utils/FilterTexture.js b/src/pixi/renderers/webgl/utils/FilterTexture.js index e7af279..9dada23 100644 --- a/src/pixi/renderers/webgl/utils/FilterTexture.js +++ b/src/pixi/renderers/webgl/utils/FilterTexture.js @@ -19,6 +19,7 @@ */ this.gl = gl; + // next time to create a frame buffer and texture this.frameBuffer = gl.createFramebuffer(); this.texture = gl.createTexture(); @@ -73,11 +74,11 @@ var gl = this.gl; gl.bindTexture(gl.TEXTURE_2D, this.texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width , height , 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + // console.log( width, width ) // update the stencil buffer width and height gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width , height ); }; /** diff --git a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js index ac1aca3..e30cd4f 100755 --- a/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js +++ b/src/pixi/renderers/webgl/utils/WebGLSpriteBatch.js @@ -78,6 +78,9 @@ this.setContext(gl); this.dirty = true; + + this.textures = []; + this.blendModes = []; }; /** @@ -140,15 +143,14 @@ PIXI.WebGLSpriteBatch.prototype.render = function(sprite) { var texture = sprite.texture; - - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== sprite.blendMode; - + + //TODO set blend modes.. // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(sprite.blendMode); } // get the uvs for the texture @@ -191,13 +193,15 @@ } var index = this.currentBatchSize * 4 * this.vertSize; + + var resolution = texture.baseTexture.resolution; - var worldTransform = sprite.worldTransform;//.toArray(); + var worldTransform = sprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -242,8 +246,10 @@ verticies[index++] = tint; // increment the batchsize - this.currentBatchSize++; + this.textures[this.currentBatchSize] = sprite.texture.baseTexture; + this.blendModes[this.currentBatchSize] = sprite.blendMode; + this.currentBatchSize++; }; @@ -257,14 +263,13 @@ { var texture = tilingSprite.tilingTexture; - var blendChange = this.renderSession.blendModeManager.currentBlendMode !== tilingSprite.blendMode; - + // check texture.. - if(texture.baseTexture !== this.currentBaseTexture || this.currentBatchSize >= this.size || blendChange) + if(this.currentBatchSize >= this.size) { + //return; this.flush(); this.currentBaseTexture = texture.baseTexture; - this.renderSession.blendModeManager.setBlendMode(tilingSprite.blendMode); } // set the textures uvs temporarily @@ -305,8 +310,8 @@ var height = tilingSprite.height; // TODO trim?? - var aX = tilingSprite.anchor.x; // - tilingSprite.texture.trim.x - var aY = tilingSprite.anchor.y; //- tilingSprite.texture.trim.y + var aX = tilingSprite.anchor.x; + var aY = tilingSprite.anchor.y; var w0 = width * (1-aX); var w1 = width * -aX; @@ -315,12 +320,14 @@ var index = this.currentBatchSize * 4 * this.vertSize; + var resolution = texture.baseTexture.resolution; + var worldTransform = tilingSprite.worldTransform; - var a = worldTransform.a;//[0]; - var b = worldTransform.c;//[3]; - var c = worldTransform.b;//[1]; - var d = worldTransform.d;//[4]; + var a = worldTransform.a / resolution;//[0]; + var b = worldTransform.c / resolution;//[3]; + var c = worldTransform.b / resolution;//[1]; + var d = worldTransform.d / resolution;//[4]; var tx = worldTransform.tx;//[2]; var ty = worldTransform.ty;///[5]; @@ -335,7 +342,7 @@ verticies[index++] = tint; // xy - verticies[index++] = a * w0 + c * h1 + tx; + verticies[index++] = (a * w0 + c * h1 + tx); verticies[index++] = d * h1 + b * w0 + ty; // uv verticies[index++] = uvs.x1; @@ -365,6 +372,8 @@ verticies[index++] = tint; // increment the batchs + this.textures[this.currentBatchSize] = texture.baseTexture; + this.blendModes[this.currentBatchSize] = tilingSprite.blendMode; this.currentBatchSize++; }; @@ -381,10 +390,9 @@ if (this.currentBatchSize===0)return; var gl = this.gl; - + this.renderSession.shaderManager.setShader(this.renderSession.shaderManager.defaultShader); - //TODO - im usre this can be done better - will look to tweak this for 1.7.. if(this.dirty) { this.dirty = false; @@ -407,15 +415,6 @@ } - // bind the current texture - gl.bindTexture(gl.TEXTURE_2D, this.currentBaseTexture._glTextures[gl.id] || PIXI.createWebGLTexture(this.currentBaseTexture, gl)); - - // check if a texture is dirty.. - if(this.currentBaseTexture._dirty[gl.id]) - { - PIXI.updateWebGLTexture(this.currentBaseTexture, gl); - } - // upload the verts to the buffer if(this.currentBatchSize > ( this.size * 0.5 ) ) { @@ -424,19 +423,59 @@ else { var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); } - // var view = this.vertices.subarray(0, this.currentBatchSize * 4 * this.vertSize); - //gl.bufferSubData(gl.ARRAY_BUFFER, 0, view); - - // now draw those suckas! - gl.drawElements(gl.TRIANGLES, this.currentBatchSize * 6, gl.UNSIGNED_SHORT, 0); - + var nextTexture, nextBlendMode; + var batchSize = 0; + var start = 0; + + var currentBaseTexture = null; + var currentBlendMode = this.renderSession.blendModeManager.currentBlendMode; + + for (var i = 0, j = this.currentBatchSize; i < j; i++) { + + nextTexture = this.textures[i]; + nextBlendMode = this.blendModes[i]; + + if(currentBaseTexture !== nextTexture || currentBlendMode !== nextBlendMode) + { + this.renderBatch(currentBaseTexture, batchSize, start); + + start = i; + batchSize = 0; + currentBaseTexture = nextTexture; + currentBlendMode = nextBlendMode; + + this.renderSession.blendModeManager.setBlendMode( currentBlendMode ); + } + + batchSize++; + } + + this.renderBatch(currentBaseTexture, batchSize, start); + // then reset the batch! this.currentBatchSize = 0; +}; +PIXI.WebGLSpriteBatch.prototype.renderBatch = function(texture, size, startIndex) +{ + if(size === 0)return; + + var gl = this.gl; + // bind the current texture + gl.bindTexture(gl.TEXTURE_2D, texture._glTextures[gl.id] || PIXI.createWebGLTexture(texture, gl)); + + // check if a texture is dirty.. + if(texture._dirty[gl.id]) + { + PIXI.updateWebGLTexture(this.currentBaseTexture, gl); + } + + // now draw those suckas! + gl.drawElements(gl.TRIANGLES, size * 6, gl.UNSIGNED_SHORT, startIndex * 6 * 2); + // increment the draw count this.renderSession.drawCount++; }; @@ -478,4 +517,3 @@ this.gl = null; }; - diff --git a/src/pixi/text/Text.js b/src/pixi/text/Text.js index 2b2e26a..3f94b5d 100644 --- a/src/pixi/text/Text.js +++ b/src/pixi/text/Text.js @@ -42,10 +42,16 @@ */ this.context = this.canvas.getContext('2d'); + + this.resolution = 1; + + PIXI.Sprite.call(this, PIXI.Texture.fromCanvas(this.canvas)); this.setText(text); this.setStyle(style); + + }; // constructor @@ -160,6 +166,8 @@ */ PIXI.Text.prototype.updateText = function() { + this.texture.baseTexture.resolution = this.resolution; + this.context.font = this.style.font; var outputText = this.text; @@ -184,14 +192,16 @@ var width = maxLineWidth + this.style.strokeThickness; if(this.style.dropShadow)width += this.style.dropShadowDistance; - this.canvas.width = width + this.context.lineWidth; + this.canvas.width = ( width + this.context.lineWidth ) * this.resolution; //calculate text height var lineHeight = this.determineFontHeight('font: ' + this.style.font + ';') + this.style.strokeThickness; var height = lineHeight * lines.length; if(this.style.dropShadow)height += this.style.dropShadowDistance; - this.canvas.height = height; + this.canvas.height = height * this.resolution; + + this.context.scale( this.resolution, this.resolution); if(navigator.isCocoonJS) this.context.clearRect(0,0,this.canvas.width,this.canvas.height); @@ -203,6 +213,7 @@ var linePositionX; var linePositionY; + if(this.style.dropShadow) { this.context.fillStyle = this.style.dropShadowColor; @@ -284,7 +295,6 @@ this._width = this.canvas.width; this._height = this.canvas.height; - this.requiresUpdate = true; }; /** @@ -296,30 +306,38 @@ */ PIXI.Text.prototype._renderWebGL = function(renderSession) { - if(this.requiresUpdate) + if(this.dirty) { - this.requiresUpdate = false; + this.resolution = renderSession.resolution; + + this.updateText(); + this.dirty = false; + PIXI.updateWebGLTexture(this.texture.baseTexture, renderSession.gl); } PIXI.Sprite.prototype._renderWebGL.call(this, renderSession); }; + /** - * Updates the transform of this object - * - * @method updateTransform - * @private - */ -PIXI.Text.prototype.updateTransform = function() +* Renders the object using the WebGL renderer +* +* @method _renderWebGL +* @param renderSession {RenderSession} +* @private +*/ +PIXI.Text.prototype._renderCanvas = function(renderSession) { if(this.dirty) { + this.resolution = renderSession.resolution; + this.updateText(); this.dirty = false; } - - PIXI.Sprite.prototype.updateTransform.call(this); + + PIXI.Sprite.prototype._renderCanvas.call(this, renderSession); }; /* diff --git a/src/pixi/textures/BaseTexture.js b/src/pixi/textures/BaseTexture.js index 7e08fcc..3ab40bf 100644 --- a/src/pixi/textures/BaseTexture.js +++ b/src/pixi/textures/BaseTexture.js @@ -22,6 +22,14 @@ PIXI.EventTarget.call( this ); /** + * The Resolution of the texture. + * + * @property resolution + * @type Number + */ + this.resolution = 1; + + /** * [read-only] The width of the base texture set when the image has loaded * * @property width @@ -76,6 +84,9 @@ */ this.premultipliedAlpha = true; + + + // used for webGL this._glTextures = []; @@ -178,6 +189,7 @@ if(!baseTexture) { + // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 var image = new Image();//document.createElement('img'); @@ -185,10 +197,17 @@ { image.crossOrigin = ''; } + image.src = imageUrl; baseTexture = new PIXI.BaseTexture(image, scaleMode); baseTexture.imageUrl = imageUrl; PIXI.BaseTextureCache[imageUrl] = baseTexture; + + // if there is an @2x at the end of the url we are going to assume its a highres image + if( imageUrl.indexOf(PIXI.RETINA_PREFIX + '.') !== -1) + { + baseTexture.resolution = 2; + } } return baseTexture; diff --git a/src/pixi/textures/RenderTexture.js b/src/pixi/textures/RenderTexture.js index 82a37f5..f1e4ad1 100644 --- a/src/pixi/textures/RenderTexture.js +++ b/src/pixi/textures/RenderTexture.js @@ -30,8 +30,9 @@ * @param width {Number} The width of the render texture * @param height {Number} The height of the render texture * @param scaleMode {Number} Should be one of the PIXI.scaleMode consts + * @param resolution {Number} The resolution of the texture being generated */ -PIXI.RenderTexture = function(width, height, renderer, scaleMode) +PIXI.RenderTexture = function(width, height, renderer, scaleMode, resolution) { PIXI.EventTarget.call( this ); @@ -50,6 +51,14 @@ * @type Number */ this.height = height || 100; + + /** + * The Resolution of the texture. + * + * @property resolution + * @type Number + */ + this.resolution = resolution || 1; /** * The framing rectangle of the render texture @@ -57,7 +66,7 @@ * @property frame * @type Rectangle */ - this.frame = new PIXI.Rectangle(0, 0, this.width, this.height); + this.frame = new PIXI.Rectangle(0, 0, this.width * this.resolution, this.height * this.resolution); /** * This is the area of the BaseTexture image to actually copy to the Canvas / WebGL when rendering, @@ -66,8 +75,9 @@ * @property crop * @type Rectangle */ - this.crop = new PIXI.Rectangle(0, 0, this.width, this.height); - + this.crop = new PIXI.Rectangle(0, 0, this.width * this.resolution, this.height * this.resolution); + + /** * The base texture object that this texture uses * @@ -75,10 +85,12 @@ * @type BaseTexture */ this.baseTexture = new PIXI.BaseTexture(); - this.baseTexture.width = this.width; - this.baseTexture.height = this.height; + this.baseTexture.width = this.width * this.resolution; + this.baseTexture.height = this.height * this.resolution; this.baseTexture._glTextures = []; + this.baseTexture.resolution = this.resolution; + this.baseTexture.scaleMode = scaleMode || PIXI.scaleModes.DEFAULT; this.baseTexture.hasLoaded = true; @@ -90,16 +102,16 @@ { var gl = this.renderer.gl; - this.textureBuffer = new PIXI.FilterTexture(gl, this.width, this.height, this.baseTexture.scaleMode); + this.textureBuffer = new PIXI.FilterTexture(gl, this.width * this.resolution, this.height * this.resolution, this.baseTexture.scaleMode); this.baseTexture._glTextures[gl.id] = this.textureBuffer.texture; this.render = this.renderWebGL; - this.projection = new PIXI.Point(this.width/2 , -this.height/2); + this.projection = new PIXI.Point(this.width*0.5, -this.height*0.5); } else { this.render = this.renderCanvas; - this.textureBuffer = new PIXI.CanvasBuffer(this.width, this.height); + this.textureBuffer = new PIXI.CanvasBuffer(this.width* this.resolution, this.height* this.resolution); this.baseTexture.source = this.textureBuffer.canvas; } @@ -146,7 +158,7 @@ } if(!this.valid)return; - this.textureBuffer.resize(this.width, this.height); + this.textureBuffer.resize(this.width * this.resolution, this.height * this.resolution); }; @@ -183,7 +195,7 @@ gl.colorMask(true, true, true, true); - gl.viewport(0, 0, this.width, this.height); + gl.viewport(0, 0, this.width * this.resolution, this.height * this.resolution); gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer ); @@ -254,6 +266,9 @@ displayObject.worldTransform.ty = 0; } + // displayObject.worldTransform.a = 0.5; + // displayObject.worldTransform.d = 0.5; + for(var i = 0, j = children.length; i < j; i++) { children[i].updateTransform(); @@ -263,8 +278,15 @@ var context = this.textureBuffer.context; - this.renderer.renderDisplayObject(displayObject, context); + var realResolution = this.renderer.resolution; + this.renderer.resolution = this.resolution; + //this.baseTexture.resolution = 2; + + this.renderer.renderDisplayObject(displayObject, context); + + this.renderer.resolution = realResolution; + context.setTransform(1,0,0,1,0,0); displayObject.worldTransform = originalWorldTransform; diff --git a/src/pixi/utils/Detector.js b/src/pixi/utils/Detector.js index c374ad6..c0bd1ed 100644 --- a/src/pixi/utils/Detector.js +++ b/src/pixi/utils/Detector.js @@ -10,13 +10,16 @@ * @static * @param width=800 {Number} the width of the renderers view * @param height=600 {Number} the height of the renderers view - * @param [view] {Canvas} the canvas to use as a view, optional - * @param [transparent=false] {Boolean} the transparency of the render view, default false - * @param [antialias=false] {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * @param [preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * + * + * @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.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 + * */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.autoDetectRenderer = function(width, height, options) { if(!width)width = 800; if(!height)height = 600; @@ -32,10 +35,10 @@ if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias, preserveDrawingBuffer); + return new PIXI.WebGLRenderer(width, height, options); } - return new PIXI.CanvasRenderer(width, height, view, transparent); + return new PIXI.CanvasRenderer(width, height, options); }; /** @@ -47,13 +50,16 @@ * @static * @param width=800 {Number} the width of the renderers view * @param height=600 {Number} the height of the renderers view - * @param [view] {Canvas} the canvas to use as a view, optional - * @param [transparent=false] {Boolean} the transparency of the render view, default false - * @param [antialias=false] {Boolean} sets antialias (only applicable in webGL chrome at the moment) - * @param [preserveDrawingBuffer=false] {Boolean} enables drawing buffer preservation, enable this if you need to call toDataUrl on the webgl context - * + * + * @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.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 + * */ -PIXI.autoDetectRecommendedRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) +PIXI.autoDetectRecommendedRenderer = function(width, height, options) { if(!width)width = 800; if(!height)height = 600; @@ -71,8 +77,8 @@ if( webgl && !isAndroid) { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias, preserveDrawingBuffer); + return new PIXI.WebGLRenderer(width, height, options); } - return new PIXI.CanvasRenderer(width, height, view, transparent); + return new PIXI.CanvasRenderer(width, height, options); };