From cca955f1fd36975219d0f09425369655be73b507 Mon Sep 17 00:00:00 2001 From: photonstorm Date: Thu, 28 Aug 2014 23:11:13 +0100 Subject: [PATCH] Updated to latest version of Pixi. --- src/pixi/InteractionData.js | 18 ++- src/pixi/InteractionManager.js | 76 +++++++---- src/pixi/core/Circle.js | 2 +- src/pixi/core/Matrix.js | 39 ++++++ src/pixi/display/DisplayObject.js | 127 +++++++++++++----- src/pixi/display/DisplayObjectContainer.js | 4 + src/pixi/display/Sprite.js | 2 +- src/pixi/extras/Rope.js | 1 + src/pixi/extras/Strip.js | 27 +++- src/pixi/extras/TilingSprite.js | 4 +- src/pixi/loaders/BitmapFontLoader.js | 11 +- src/pixi/loaders/ImageLoader.js | 22 +-- src/pixi/loaders/JsonLoader.js | 28 ++-- src/pixi/primitives/Graphics.js | 2 +- src/pixi/renderers/webgl/WebGLRenderer.js | 26 ++-- .../webgl/shaders/PrimitiveShader.js | 2 +- .../renderers/webgl/shaders/StripShader.js | 14 ++ .../renderers/webgl/utils/FilterTexture.js | 2 +- .../renderers/webgl/utils/WebGLGraphics.js | 2 - .../renderers/webgl/utils/WebGLMaskManager.js | 9 +- .../webgl/utils/WebGLShaderManager.js | 5 +- .../webgl/utils/WebGLStencilManager.js | 6 +- src/pixi/text/Text.js | 1 - src/pixi/textures/BaseTexture.js | 10 +- src/pixi/textures/RenderTexture.js | 70 ++++++++++ src/pixi/textures/Texture.js | 19 +-- src/pixi/utils/Detector.js | 10 +- src/pixi/utils/Utils.js | 61 +++++---- 28 files changed, 400 insertions(+), 200 deletions(-) diff --git a/src/pixi/InteractionData.js b/src/pixi/InteractionData.js index 9274ad18a..ea7737062 100644 --- a/src/pixi/InteractionData.js +++ b/src/pixi/InteractionData.js @@ -1,7 +1,7 @@ /** * @author Mat Groves http://matgroves.com/ @Doormat23 */ - + /** * Holds all information related to an Interaction event * @@ -18,7 +18,7 @@ PIXI.InteractionData = function() */ this.global = new PIXI.Point(); - + /** * The target Sprite that was interacted with * @@ -41,9 +41,10 @@ PIXI.InteractionData = function() * * @method getLocalPosition * @param displayObject {DisplayObject} The DisplayObject that you would like the local coords off + * @param [point] {Point} A Point object in which to store the value, optional (otherwise will create a new point) * @return {Point} A point containing the coordinates of the InteractionData position relative to the DisplayObject */ -PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) +PIXI.InteractionData.prototype.getLocalPosition = function(displayObject, point) { var worldTransform = displayObject.worldTransform; var global = this.global; @@ -52,10 +53,15 @@ PIXI.InteractionData.prototype.getLocalPosition = function(displayObject) var a00 = worldTransform.a, a01 = worldTransform.b, a02 = worldTransform.tx, a10 = worldTransform.c, a11 = worldTransform.d, a12 = worldTransform.ty, id = 1 / (a00 * a11 + a01 * -a10); + + point = point || new PIXI.Point(); + + point.x = a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id; + point.y = a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id; + // set the mouse coords... - return new PIXI.Point(a11 * id * global.x + -a01 * id * global.y + (a12 * a01 - a02 * a11) * id, - a00 * id * global.y + -a10 * id * global.x + (-a12 * a00 + a02 * a10) * id); + return point; }; // constructor -PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; \ No newline at end of file +PIXI.InteractionData.prototype.constructor = PIXI.InteractionData; diff --git a/src/pixi/InteractionManager.js b/src/pixi/InteractionManager.js index 7694867c3..3998b67d4 100644 --- a/src/pixi/InteractionManager.js +++ b/src/pixi/InteractionManager.js @@ -381,22 +381,29 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) //stage.__i var length = this.interactiveItems.length; + var e = this.mouse.originalEvent; + var isRightButton = e.button === 2 || e.which === 3; + var downFunction = isRightButton ? 'rightdown' : 'mousedown'; + var clickFunction = isRightButton ? 'rightclick' : 'click'; + var buttonIsDown = isRightButton ? '__rightIsDown' : '__mouseIsDown'; + var isDown = isRightButton ? '__isRightDown' : '__isDown'; + // while // hit test for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - if(item.mousedown || item.click) + if(item[downFunction] || item[clickFunction]) { - item.__mouseIsDown = true; + item[buttonIsDown] = true; item.__hit = this.hitTest(item, this.mouse); if(item.__hit) { //call the function! - if(item.mousedown)item.mousedown(this.mouse); - item.__isDown = true; + if(item[downFunction])item[downFunction](this.mouse); + item[isDown] = true; // just the one! if(!item.interactiveChildren)break; @@ -412,13 +419,15 @@ PIXI.InteractionManager.prototype.onMouseDown = function(event) * @param event {Event} The DOM event of a mouse button being moved out * @private */ -PIXI.InteractionManager.prototype.onMouseOut = function() +PIXI.InteractionManager.prototype.onMouseOut = function(event) { if(this.dirty) { this.rebuildInteractiveGraph(); } + this.mouse.originalEvent = event || window.event; //IE uses window.event + var length = this.interactiveItems.length; this.interactionDOMElement.style.cursor = 'inherit'; @@ -460,36 +469,46 @@ PIXI.InteractionManager.prototype.onMouseUp = function(event) var length = this.interactiveItems.length; var up = false; + var e = this.mouse.originalEvent; + var isRightButton = e.button === 2 || e.which === 3; + + var upFunction = isRightButton ? 'rightup' : 'mouseup'; + var clickFunction = isRightButton ? 'rightclick' : 'click'; + var upOutsideFunction = isRightButton ? 'rightupoutside' : 'mouseupoutside'; + var isDown = isRightButton ? '__isRightDown' : '__isDown'; + for (var i = 0; i < length; i++) { var item = this.interactiveItems[i]; - item.__hit = this.hitTest(item, this.mouse); - - if(item.__hit && !up) + if(item[clickFunction] || item[upFunction] || item[upOutsideFunction]) { - //call the function! - if(item.mouseup) + item.__hit = this.hitTest(item, this.mouse); + + if(item.__hit && !up) { - item.mouseup(this.mouse); + //call the function! + if(item[upFunction]) + { + item[upFunction](this.mouse); + } + if(item[isDown]) + { + if(item[clickFunction])item[clickFunction](this.mouse); + } + + if(!item.interactiveChildren)up = true; } - if(item.__isDown) + else { - if(item.click)item.click(this.mouse); + if(item[isDown]) + { + if(item[upOutsideFunction])item[upOutsideFunction](this.mouse); + } } - if(!item.interactiveChildren)up = true; + item[isDown] = false; } - else - { - if(item.__isDown) - { - if(item.mouseupoutside)item.mouseupoutside(this.mouse); - } - } - - item.__isDown = false; - //} } }; @@ -596,7 +615,8 @@ PIXI.InteractionManager.prototype.onTouchMove = function(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); - if(navigator.isCocoonJS) { + 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; touchData.global.y = touchEvent.clientY; } @@ -640,7 +660,8 @@ PIXI.InteractionManager.prototype.onTouchStart = function(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); - if(navigator.isCocoonJS) { + 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; touchData.global.y = touchEvent.clientY; } @@ -695,7 +716,8 @@ PIXI.InteractionManager.prototype.onTouchEnd = function(event) 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); - if(navigator.isCocoonJS) { + 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; touchData.global.y = touchEvent.clientY; } diff --git a/src/pixi/core/Circle.js b/src/pixi/core/Circle.js index 47d2e7381..cc39a2834 100644 --- a/src/pixi/core/Circle.js +++ b/src/pixi/core/Circle.js @@ -77,7 +77,7 @@ PIXI.Circle.prototype.contains = function(x, y) */ PIXI.Circle.prototype.getBounds = function() { - return new PIXI.Rectangle(this.x - this.radius, this.y - this.radius, this.width, this.height); + return new PIXI.Rectangle(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2); }; // constructor diff --git a/src/pixi/core/Matrix.js b/src/pixi/core/Matrix.js index cc4ebe26a..7416d207c 100644 --- a/src/pixi/core/Matrix.js +++ b/src/pixi/core/Matrix.js @@ -78,6 +78,45 @@ PIXI.Matrix.prototype.toArray = function(transpose) return array; }; +/** + * Get a new position with the current transormation applied. + * Can be used to go from a child's coordinate space to the world coordinate space. (e.g. rendering) + * + * @method apply + * @param pos {Point} The origin + * @param [newPos] {Point} The point that the new position is assigned to (allowed to be same as input) + * @return {Point} The new point, transformed trough this matrix + */ +PIXI.Matrix.prototype.apply = function(pos, newPos) +{ + newPos = newPos || new PIXI.Point(); + + newPos.x = this.a * pos.x + this.b * pos.y + this.tx; + newPos.y = this.c * pos.x + this.d * pos.y + this.ty; + + return newPos; +}; + +/** + * Get a new position with the inverse of the current transormation applied. + * Can be used to go from the world coordinate space to a child's coordinate space. (e.g. input) + * + * @method apply + * @param pos {Point} The origin + * @param [newPos] {Point} The point that the new position is assigned to (allowed to be same as input) + * @return {Point} The new point, inverse-transformed trough this matrix + */ +PIXI.Matrix.prototype.applyInverse = function(pos, newPos) +{ + newPos = newPos || new PIXI.Point(); + + var id = 1 / (this.a * this.d + this.b * -this.c); + newPos.x = this.d * id * pos.x - this.b * id * pos.y + (this.ty * this.b - this.tx * this.d) * id; + newPos.y = this.a * id * pos.y - this.c * id * pos.x + (this.tx * this.c - this.ty * this.a) * id; + + return newPos; +}; + PIXI.identityMatrix = new PIXI.Matrix(); PIXI.determineMatrixArrayType = function() { diff --git a/src/pixi/display/DisplayObject.js b/src/pixi/display/DisplayObject.js index ee50166c8..4a7b13272 100644 --- a/src/pixi/display/DisplayObject.js +++ b/src/pixi/display/DisplayObject.js @@ -3,7 +3,7 @@ */ /** - * The base class for all objects that are rendered on the screen. + * The base class for all objects that are rendered on the screen. * This is an abstract class and should not be used on its own rather it should be extended. * * @class DisplayObject @@ -123,7 +123,7 @@ PIXI.DisplayObject = function() /** * This is the cursor that will be used when the mouse is over this object. To enable this the element must have interaction = true and buttonMode = true - * + * * @property defaultCursor * @type String * @@ -203,33 +203,7 @@ PIXI.DisplayObject = function() /* * MOUSE Callbacks */ - - /** - * A callback that is used when the users clicks on the displayObject with their mouse - * @method click - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user clicks the mouse down over the sprite - * @method mousedown - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject - * for this callback to be fired the mouse must have been pressed down over the displayObject - * @method mouseup - * @param interactionData {InteractionData} - */ - - /** - * A callback that is used when the user releases the mouse that was over the displayObject but is no longer over the displayObject - * for this callback to be fired, The touch must have started over the displayObject - * @method mouseupoutside - * @param interactionData {InteractionData} - */ - + /** * A callback that is used when the users mouse rolls over the displayObject * @method mouseover @@ -242,6 +216,59 @@ PIXI.DisplayObject = function() * @param interactionData {InteractionData} */ + //Left button + /** + * A callback that is used when the users clicks on the displayObject with their mouse's left button + * @method click + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user clicks the mouse's left button down over the sprite + * @method mousedown + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse's left button that was over the displayObject + * for this callback to be fired, the mouse's left button must have been pressed down over the displayObject + * @method mouseup + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse's left button that was over the displayObject but is no longer over the displayObject + * for this callback to be fired, the mouse's left button must have been pressed down over the displayObject + * @method mouseupoutside + * @param interactionData {InteractionData} + */ + + //Right button + /** + * A callback that is used when the users clicks on the displayObject with their mouse's right button + * @method rightclick + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user clicks the mouse's right button down over the sprite + * @method rightdown + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse's right button that was over the displayObject + * for this callback to be fired the mouse's right button must have been pressed down over the displayObject + * @method rightup + * @param interactionData {InteractionData} + */ + + /** + * A callback that is used when the user releases the mouse's right button that was over the displayObject but is no longer over the displayObject + * for this callback to be fired, the mouse's right button must have been pressed down over the displayObject + * @method rightupoutside + * @param interactionData {InteractionData} + */ /* * TOUCH Callbacks @@ -481,7 +508,6 @@ PIXI.DisplayObject.prototype.getLocalBounds = function() return this.getBounds(PIXI.identityMatrix);///PIXI.EmptyRectangle(); }; - /** * Sets the object's stage reference, the stage this object is connected to * @@ -509,10 +535,41 @@ PIXI.DisplayObject.prototype.updateCache = function() this._generateCachedSprite(); }; +/** + * Calculates the global position of the display object + * + * @method toGlobal + * @param position {Point} The world origin to calculate from + * @return {Point} A point object representing the position of this object + */ +PIXI.DisplayObject.prototype.toGlobal = function(pos) +{ + this.updateTransform(); + return this.worldTransform.apply(pos); +}; + +/** + * Calculates the local position of the display object relative to another point + * + * @method toGlobal + * @param position {Point} The world origin to calculate from + * @param [from] {DisplayObject} The DisplayObject to calculate the global position from + * @return {Point} A point object representing the position of this object + */ +PIXI.DisplayObject.prototype.toLocal = function(pos, from) +{ + if (from) + { + pos = from.toGlobal(pos); + } + this.updateTransform(); + return this.worldTransform.applyInverse(pos); +}; + PIXI.DisplayObject.prototype._renderCachedSprite = function(renderSession) { this._cachedSprite.worldAlpha = this.worldAlpha; - + if(renderSession.gl) { PIXI.Sprite.prototype._renderWebGL.call(this._cachedSprite, renderSession); @@ -527,11 +584,11 @@ PIXI.DisplayObject.prototype._generateCachedSprite = function()//renderSession) { this._cacheAsBitmap = false; var bounds = this.getLocalBounds(); - + if(!this._cachedSprite) { var renderTexture = new PIXI.RenderTexture(bounds.width | 0, bounds.height | 0);//, renderSession.renderer); - + this._cachedSprite = new PIXI.Sprite(renderTexture); this._cachedSprite.worldTransform = this.worldTransform; } @@ -559,7 +616,7 @@ PIXI.DisplayObject.prototype._generateCachedSprite = function()//renderSession) * Renders the object using the WebGL renderer * * @method _renderWebGL -* @param renderSession {RenderSession} +* @param renderSession {RenderSession} * @private */ PIXI.DisplayObject.prototype._destroyCachedSprite = function() @@ -585,7 +642,7 @@ PIXI.DisplayObject.prototype._renderWebGL = function(renderSession) * Renders the object using the Canvas renderer * * @method _renderCanvas -* @param renderSession {RenderSession} +* @param renderSession {RenderSession} * @private */ PIXI.DisplayObject.prototype._renderCanvas = function(renderSession) diff --git a/src/pixi/display/DisplayObjectContainer.js b/src/pixi/display/DisplayObjectContainer.js index 4e28f7f7a..999c7742d 100644 --- a/src/pixi/display/DisplayObjectContainer.js +++ b/src/pixi/display/DisplayObjectContainer.js @@ -226,6 +226,10 @@ PIXI.DisplayObjectContainer.prototype.removeChildren = function(beginIndex, endI } return removed; } + else if (range === 0 && this.children.length === 0) + { + return []; + } else { throw new Error( 'Range Error, numeric values are outside the acceptable range' ); diff --git a/src/pixi/display/Sprite.js b/src/pixi/display/Sprite.js index 5d810eb8b..e499a30a9 100644 --- a/src/pixi/display/Sprite.js +++ b/src/pixi/display/Sprite.js @@ -308,7 +308,7 @@ PIXI.Sprite.prototype._renderWebGL = function(renderSession) PIXI.Sprite.prototype._renderCanvas = function(renderSession) { // If the sprite is not visible or the alpha is 0 then no need to render this element - if (this.visible === false || this.alpha === 0) return; + if (this.visible === false || this.alpha === 0 || this.texture.crop.width <= 0 || this.texture.crop.height <= 0) return; if (this.blendMode !== renderSession.currentBlendMode) { diff --git a/src/pixi/extras/Rope.js b/src/pixi/extras/Rope.js index c51b7250b..f4b085231 100644 --- a/src/pixi/extras/Rope.js +++ b/src/pixi/extras/Rope.js @@ -5,6 +5,7 @@ * * @class Rope * @constructor + * @extends Strip * @param texture {Texture} The texture to use * @param points {Array} * diff --git a/src/pixi/extras/Strip.js b/src/pixi/extras/Strip.js index 0ef579962..ad6d27dd6 100644 --- a/src/pixi/extras/Strip.js +++ b/src/pixi/extras/Strip.js @@ -16,6 +16,13 @@ PIXI.Strip = function(texture) { PIXI.DisplayObjectContainer.call( this ); + + /** + * The texture of the strip + * + * @property texture + * @type Texture + */ this.texture = texture; // set up the main bits.. @@ -33,8 +40,24 @@ PIXI.Strip = function(texture) this.indices = new PIXI.Uint16Array([0, 1, 2, 3]); - + /** + * Whether the strip is dirty or not + * + * @property dirty + * @type Boolean + */ this.dirty = true; + + + /** + * if you need a padding, not yet implemented + * + * @property padding + * @type Number + */ + this.padding = 0; + // NYI, TODO padding ? + }; // constructor @@ -184,7 +207,7 @@ PIXI.Strip.prototype._renderCanvas = function(renderSession) var x0 = verticies[index], x1 = verticies[index+2], x2 = verticies[index+4]; var y0 = verticies[index+1], y1 = verticies[index+3], y2 = verticies[index+5]; - if(true) + if(this.padding === 0) { //expand(); diff --git a/src/pixi/extras/TilingSprite.js b/src/pixi/extras/TilingSprite.js index 41e88a68b..4bdc23ed1 100644 --- a/src/pixi/extras/TilingSprite.js +++ b/src/pixi/extras/TilingSprite.js @@ -186,7 +186,7 @@ PIXI.TilingSprite.prototype._renderWebGL = function(renderSession) renderSession.spriteBatch.stop(); if (this._filters) renderSession.filterManager.popFilter(); - if (this._mask) renderSession.maskManager.popMask(renderSession); + if (this._mask) renderSession.maskManager.popMask(this._mask, renderSession); renderSession.spriteBatch.start(); }; @@ -452,4 +452,4 @@ PIXI.TilingSprite.prototype.generateTilingTexture = function(forcePowerOfTwo) this.refreshTexture = false; this.tilingTexture.baseTexture._powerOf2 = true; -}; \ No newline at end of file +}; diff --git a/src/pixi/loaders/BitmapFontLoader.js b/src/pixi/loaders/BitmapFontLoader.js index 78488d2f8..f87fbdd30 100644 --- a/src/pixi/loaders/BitmapFontLoader.js +++ b/src/pixi/loaders/BitmapFontLoader.js @@ -68,11 +68,7 @@ PIXI.BitmapFontLoader.prototype.constructor = PIXI.BitmapFontLoader; PIXI.BitmapFontLoader.prototype.load = function() { this.ajaxRequest = new PIXI.AjaxRequest(); - var scope = this; - this.ajaxRequest.onreadystatechange = function() - { - scope.onXMLLoaded(); - }; + this.ajaxRequest.onreadystatechange = this.onXMLLoaded.bind(this); this.ajaxRequest.open('GET', this.url, true); if (this.ajaxRequest.overrideMimeType) this.ajaxRequest.overrideMimeType('application/xml'); @@ -153,10 +149,7 @@ PIXI.BitmapFontLoader.prototype.onXMLLoaded = function() PIXI.BitmapText.fonts[data.font] = data; - var scope = this; - image.addEventListener('loaded', function() { - scope.onLoaded(); - }); + image.addEventListener('loaded', this.onLoaded.bind(this)); image.load(); } } diff --git a/src/pixi/loaders/ImageLoader.js b/src/pixi/loaders/ImageLoader.js index 9e998b0a8..ad4c61c97 100644 --- a/src/pixi/loaders/ImageLoader.js +++ b/src/pixi/loaders/ImageLoader.js @@ -4,7 +4,7 @@ /** * The image loader class is responsible for loading images file formats ('jpeg', 'jpg', 'png' and 'gif') - * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrameId() and PIXI.Sprite.fromFrameId() + * Once the image has been loaded it is stored in the PIXI texture cache and can be accessed though PIXI.Texture.fromFrame() and PIXI.Sprite.fromFrame() * When loaded this class will dispatch a 'loaded' event * * @class ImageLoader @@ -45,11 +45,7 @@ PIXI.ImageLoader.prototype.load = function() { if(!this.texture.baseTexture.hasLoaded) { - var scope = this; - this.texture.baseTexture.addEventListener('loaded', function() - { - scope.onLoaded(); - }); + this.texture.baseTexture.addEventListener('loaded', this.onLoaded.bind(this)); } else { @@ -88,7 +84,7 @@ PIXI.ImageLoader.prototype.loadFramedSpriteSheet = function(frameWidth, frameHei { for (var x=0; x 0 && height > 0); + + this.width = this.frame.width = this.crop.width = width; this.height = this.frame.height = this.crop.height = height; @@ -141,7 +145,9 @@ PIXI.RenderTexture.prototype.resize = function(width, height, updateBase) this.projection.y = -this.height / 2; } + if(!this.valid)return; this.textureBuffer.resize(this.width, this.height); + }; /** @@ -151,6 +157,8 @@ PIXI.RenderTexture.prototype.resize = function(width, height, updateBase) */ PIXI.RenderTexture.prototype.clear = function() { + if(!this.valid)return; + if (this.renderer.type === PIXI.WEBGL_RENDERER) { this.renderer.gl.bindFramebuffer(this.renderer.gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); @@ -169,6 +177,7 @@ PIXI.RenderTexture.prototype.clear = function() */ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, clear) { + if(!this.valid)return; //TOOD replace position with matrix.. var gl = this.renderer.gl; @@ -225,6 +234,8 @@ PIXI.RenderTexture.prototype.renderWebGL = function(displayObject, position, cle */ PIXI.RenderTexture.prototype.renderCanvas = function(displayObject, position, clear) { + if(!this.valid)return; + var children = displayObject.children; var originalWorldTransform = displayObject.worldTransform; @@ -258,5 +269,64 @@ PIXI.RenderTexture.prototype.renderCanvas = function(displayObject, position, cl displayObject.worldTransform = originalWorldTransform; }; +/** + * Will return a HTML Image of the texture + * + * @method getImage + */ +PIXI.RenderTexture.prototype.getImage = function() +{ + var image = new Image(); + image.src = this.getBase64(); + return image; +}; + +/** + * Will return a a base64 string of the texture + * + * @method getImage + */ +PIXI.RenderTexture.prototype.getBase64 = function() +{ + return this.getCanvas().toDataURL(); +}; + +PIXI.RenderTexture.prototype.getCanvas = function() +{ + if (this.renderer.type === PIXI.WEBGL_RENDERER) + { + var gl = this.renderer.gl; + var width = this.textureBuffer.width; + var height = this.textureBuffer.height; + + var webGLPixels = new Uint8Array(4 * width * height); + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.textureBuffer.frameBuffer); + gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, webGLPixels); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + + var tempCanvas = new PIXI.CanvasBuffer(width, height); + var canvasData = tempCanvas.context.getImageData(0, 0, width, height); + var canvasPixels = canvasData.data; + + for (var i = 0; i < webGLPixels.length; i+=4) + { + var alpha = webGLPixels[i+3]; + canvasPixels[i] = webGLPixels[i] * alpha; + canvasPixels[i+1] = webGLPixels[i+1] * alpha; + canvasPixels[i+2] = webGLPixels[i+2] * alpha; + canvasPixels[i+3] = alpha; + } + + tempCanvas.context.putImageData(canvasData, 0, 0); + + return tempCanvas.canvas; + } + else + { + return this.textureBuffer.canvas; + } +}; + PIXI.RenderTexture.tempMatrix = new PIXI.Matrix(); diff --git a/src/pixi/textures/Texture.js b/src/pixi/textures/Texture.js index 070d14c7f..f2e5a0fca 100644 --- a/src/pixi/textures/Texture.js +++ b/src/pixi/textures/Texture.js @@ -63,7 +63,7 @@ PIXI.Texture = function(baseTexture, frame) * @type Rectangle */ this.trim = null; - + /** * This will let the renderer know if the texture is valid. If its not then it cannot be rendered. * @@ -72,14 +72,6 @@ PIXI.Texture = function(baseTexture, frame) */ this.valid = false; - /** - * The context scope under which events are run. - * - * @property scope - * @type Object - */ - this.scope = this; - /** * The WebGL UV data cache. * @@ -88,7 +80,7 @@ PIXI.Texture = function(baseTexture, frame) * @type Object */ this._uvs = null; - + /** * The width of the Texture in pixels. * @@ -121,8 +113,7 @@ PIXI.Texture = function(baseTexture, frame) } else { - var scope = this; - baseTexture.addEventListener('loaded', function(){ scope.onBaseTextureLoaded(); }); + baseTexture.addEventListener('loaded', this.onBaseTextureLoaded.bind(this)); } }; @@ -141,10 +132,10 @@ PIXI.Texture.prototype.onBaseTextureLoaded = function() baseTexture.removeEventListener('loaded', this.onLoaded); if (this.noFrame) this.frame = new PIXI.Rectangle(0, 0, baseTexture.width, baseTexture.height); - + this.setFrame(this.frame); - this.scope.dispatchEvent( { type: 'update', content: this } ); + this.dispatchEvent( { type: 'update', content: this } ); }; /** diff --git a/src/pixi/utils/Detector.js b/src/pixi/utils/Detector.js index 2b36feb7d..c374ad69b 100644 --- a/src/pixi/utils/Detector.js +++ b/src/pixi/utils/Detector.js @@ -13,9 +13,10 @@ * @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 * */ -PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) +PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) { if(!width)width = 800; if(!height)height = 600; @@ -31,7 +32,7 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) if( webgl ) { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias, preserveDrawingBuffer); } return new PIXI.CanvasRenderer(width, height, view, transparent); @@ -49,9 +50,10 @@ PIXI.autoDetectRenderer = function(width, height, view, transparent, antialias) * @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 * */ -PIXI.autoDetectRecommendedRenderer = function(width, height, view, transparent, antialias) +PIXI.autoDetectRecommendedRenderer = function(width, height, view, transparent, antialias, preserveDrawingBuffer) { if(!width)width = 800; if(!height)height = 600; @@ -69,7 +71,7 @@ PIXI.autoDetectRecommendedRenderer = function(width, height, view, transparent, if( webgl && !isAndroid) { - return new PIXI.WebGLRenderer(width, height, view, transparent, antialias); + return new PIXI.WebGLRenderer(width, height, view, transparent, antialias, preserveDrawingBuffer); } return new PIXI.CanvasRenderer(width, height, view, transparent); diff --git a/src/pixi/utils/Utils.js b/src/pixi/utils/Utils.js index 0b2accd25..f374d7ee4 100644 --- a/src/pixi/utils/Utils.js +++ b/src/pixi/utils/Utils.js @@ -21,32 +21,34 @@ * * @method cancelAnimationFrame */ -var lastTime = 0; -var vendors = ['ms', 'moz', 'webkit', 'o']; -for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { - window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; - window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || - window[vendors[x] + 'CancelRequestAnimationFrame']; -} +(function(window) { + var lastTime = 0; + var vendors = ['ms', 'moz', 'webkit', 'o']; + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; + window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || + window[vendors[x] + 'CancelRequestAnimationFrame']; + } -if (!window.requestAnimationFrame) { - window.requestAnimationFrame = function(callback) { - var currTime = new Date().getTime(); - var timeToCall = Math.max(0, 16 - (currTime - lastTime)); - var id = window.setTimeout(function() { callback(currTime + timeToCall); }, - timeToCall); - lastTime = currTime + timeToCall; - return id; - }; -} + if (!window.requestAnimationFrame) { + window.requestAnimationFrame = function(callback) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }; + } -if (!window.cancelAnimationFrame) { - window.cancelAnimationFrame = function(id) { - clearTimeout(id); - }; -} + if (!window.cancelAnimationFrame) { + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; + } -window.requestAnimFrame = window.requestAnimationFrame; + window.requestAnimFrame = window.requestAnimationFrame; +})(this); /** * Converts a hex color number to an [R, G, B] array @@ -75,14 +77,20 @@ PIXI.rgb2hex = function(rgb) { */ if (typeof Function.prototype.bind !== 'function') { Function.prototype.bind = (function () { - var slice = Array.prototype.slice; return function (thisArg) { - var target = this, boundArgs = slice.call(arguments, 1); + var target = this, i = arguments.length - 1, boundArgs = []; + if (i > 0) + { + boundArgs.length = i; + while (i--) boundArgs[i] = arguments[i + 1]; + } if (typeof target !== 'function') throw new TypeError(); function bound() { - var args = boundArgs.concat(slice.call(arguments)); + var i = arguments.length, args = new Array(i); + while (i--) args[i] = arguments[i]; + args = boundArgs.concat(args); target.apply(this instanceof bound ? this : thisArg, args); } @@ -164,6 +172,7 @@ PIXI.unpackColorRGB = function(r, g, b)//r, g, b, a) */ PIXI.canUseNewCanvasBlendModes = function() { + if (typeof document === 'undefined') return false; var canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = 1;