diff --git a/bin/pixi.js b/bin/pixi.js index bac9e3b..a94735c 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -4616,7 +4616,7 @@ function VertexArrayObject(gl) { - + this.nativeVaoExtension = ( gl.getExtension('OES_vertex_array_object') || gl.getExtension('MOZ_OES_vertex_array_object') || @@ -4627,7 +4627,7 @@ if(this.nativeVaoExtension) { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); } this.gl = gl; @@ -4638,7 +4638,7 @@ this.dirty = false; - + } VertexArrayObject.prototype.constructor = VertexArrayObject; @@ -4648,7 +4648,7 @@ { if(this.nativeVao) { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); if(this.dirty) { @@ -4678,18 +4678,18 @@ { var gl = this.gl; - for (var i = 0; i < this.attributes.length; i++) + for (var i = 0; i < this.attributes.length; i++) { var attrib = this.attributes[i]; - attrib.buffer.bind(); + attrib.buffer.bind(); - //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); + //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); gl.vertexAttribPointer(attrib.attribute.location, - attrib.attribute.size, attrib.type || gl.FLOAT, - attrib.normalized || false, - attrib.stride || 0, + attrib.attribute.size, attrib.type || gl.FLOAT, + attrib.normalized || false, + attrib.stride || 0, attrib.start || 0); - + gl.enableVertexAttribArray(attrib.attribute.location); }; @@ -4732,10 +4732,10 @@ // for now, no but lets see what happens in the real world! if(this.nativeVao) { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); } - for (var i = 0; i < this.attributes.length; i++) + for (var i = 0; i < this.attributes.length; i++) { var attrib = this.attributes[i]; gl.disableVertexAttribArray(attrib.attribute.location); @@ -4743,7 +4743,7 @@ this.attributes.length = 0; this.indexBuffer = null; - + return this; } @@ -4755,7 +4755,6 @@ return this; } - },{}],20:[function(require,module,exports){ /** @@ -11513,6 +11512,8 @@ .addIndex(this.indexBuffer) .addAttribute(this.buffer, shader.attributes.aVertexPosition, gl.FLOAT, false, 4 * 6, 0) .addAttribute(this.buffer, shader.attributes.aColor, gl.FLOAT, false, 4 * 6, 2 * 4); + + } WebGLGraphicsData.prototype.constructor = WebGLGraphicsData; @@ -22192,8 +22193,11 @@ },{"../core":56}],108:[function(require,module,exports){ var core = require('../core'), // a sprite use dfor rendering textures.. + Sprite = require('../core/sprites/Sprite'), tempPoint = new core.Point(), CanvasTinter = require('../core/sprites/canvas/CanvasTinter'); +var glCore = require('pixi-gl-core'), + createIndicesForQuads = require('../core/utils/createIndicesForQuads'); /** * A tiling sprite is a fast way of rendering a tiling image @@ -22207,7 +22211,23 @@ */ function TilingSprite(texture, width, height) { - core.Sprite.call(this, texture); + Sprite.call(this, texture); + + this.gl = null; + /** + * Number of values sent in the vertex buffer. + * positionX, positionY, colorR, colorG, colorB = 5 + * + * @member {number} + */ + this.vertSize = 5; + + /** + * The size of the vertex information in bytes. + * + * @member {number} + */ + this.vertByteSize = this.vertSize * 4; /** * The scaling of the image that is being tiled @@ -22253,63 +22273,40 @@ this._canvasPattern = null; //TODO move.. - this.shader = new core.Filter( - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - 'uniform mat3 projectionMatrix;', - 'uniform vec4 uFrame;', - 'uniform vec4 uTransform;', + this.vertices = new Float32Array([ + -1,-1, + 1,-1, + 1,1, + -1,1 + ]); - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + this.interleaved = new Float32Array(8 * 2); - ' vec2 coord = aTextureCoord;', - ' coord -= uTransform.xy;', - ' coord /= uTransform.zw;', - ' vTextureCoord = coord;', + for (var i = 0; i < 4; i++) { + this.interleaved[i*4] = this.vertices[(i*2)]; + this.interleaved[(i*4)+1] = this.vertices[(i*2)+1]; + this.interleaved[(i*4)+2] = this.uvs[i*2]; + this.interleaved[(i*4)+3] = this.uvs[(i*2)+1]; + } - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'), - [ - 'precision lowp float;', + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + this.indices = createIndicesForQuads(1); - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'uniform sampler2D uSampler;', - 'uniform vec4 uFrame;', - 'uniform vec2 uPixelSize;', - - 'void main(void){', - - ' vec2 coord = mod(vTextureCoord, uFrame.zw);', - ' coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);', - ' coord += uFrame.xy;', - - ' gl_FragColor = texture2D(uSampler, coord) * vColor ;', - '}' - ].join('\n'), - - // set the uniforms - { - uFrame: { type: '4fv', value: [0,0,1,1] }, - uTransform: { type: '4fv', value: [0,0,1,1] }, - uPixelSize : { type : '2fv', value: [1, 1]} - } - ); } -TilingSprite.prototype = Object.create(core.Sprite.prototype); +TilingSprite.prototype = Object.create(Sprite.prototype); TilingSprite.prototype.constructor = TilingSprite; module.exports = TilingSprite; @@ -22355,6 +22352,82 @@ return; }; +TilingSprite.prototype.initShader = function (gl) +{ + this.gl = gl; + this.shader = new glCore.GLShader(gl, + [ + 'precision lowp float;', + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + 'attribute vec4 aColor;', + + 'uniform mat3 projectionMatrix;', + + 'uniform vec4 uFrame;', + 'uniform vec4 uTransform;', + + 'varying vec2 vTextureCoord;', + 'varying vec4 vColor;', + + 'void main(void){', + ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + + ' vec2 coord = aTextureCoord;', + ' coord -= uTransform.xy;', + ' coord /= uTransform.zw;', + ' vTextureCoord = coord;', + + ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', + '}' + ].join('\n'), + [ + 'precision lowp float;', + + 'varying vec2 vTextureCoord;', + 'varying vec4 vColor;', + + 'uniform sampler2D uSampler;', + 'uniform vec4 uFrame;', + 'uniform vec2 uPixelSize;', + + 'void main(void){', + + ' vec2 coord = mod(vTextureCoord, uFrame.zw);', + ' coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);', + ' coord += uFrame.xy;', + + // ' gl_FragColor = texture2D(uSampler, coord) * vColor ;', + ' gl_FragColor = vec4(1.0);', + '}' + ].join('\n')/*8, + + // set the uniforms + { + uFrame: { type: '4fv', value: [0,0,1,1] }, + uTransform: { type: '4fv', value: [0,0,1,1] }, + uPixelSize : { type : '2fv', value: [1, 1]} + }*/ + ); + + /* + * @member {WebGLBuffer} The vertex buffer + */ + + this.vertexBuffer = glCore.GLBuffer.createVertexBuffer(this.gl, this.interleaved); + this.indexBuffer = glCore.GLBuffer.createIndexBuffer(this.gl, this.indices); + + this.vertexBuffer.upload(this.interleaved); + this.indexBuffer.upload(this.indices); + + this.vao = new glCore.VertexArrayObject(gl); + + this.vao.addIndex(this.indexBuffer) + .addAttribute(this.vertexBuffer, this.shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) + .addAttribute(this.vertexBuffer, this.shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) + .addAttribute(this.vertexBuffer, this.shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4); + // .addAttribute(this.vertexBuffer, this.shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); +}; /** * Renders the object using the WebGL renderer @@ -22367,11 +22440,23 @@ // tweak our texture temporarily.. var texture = this._texture; + + // render VertexArrayObject + + if(!texture || !texture._uvs) { return; } + if(!this.inited) + { + this.initShader(renderer.gl); + this.inited = true; + // create VertexArrayObject; + // create shader + } + var tempUvs = texture._uvs, tempWidth = texture._frame.width, tempHeight = texture._frame.height, @@ -22382,21 +22467,30 @@ texture._frame.width = this.width; texture._frame.height = this.height; - this.shader.uniforms.uPixelSize.value[0] = 1.0/tw; - this.shader.uniforms.uPixelSize.value[1] = 1.0/th; + this.shader.uniforms.uPixelSize[0] = 1.0/tw; + this.shader.uniforms.uPixelSize[1] = 1.0/th; - this.shader.uniforms.uFrame.value[0] = tempUvs.x0; - this.shader.uniforms.uFrame.value[1] = tempUvs.y0; - this.shader.uniforms.uFrame.value[2] = tempUvs.x1 - tempUvs.x0; - this.shader.uniforms.uFrame.value[3] = tempUvs.y2 - tempUvs.y0; + this.shader.uniforms.uFrame[0] = tempUvs.x0; + this.shader.uniforms.uFrame[1] = tempUvs.y0; + this.shader.uniforms.uFrame[2] = tempUvs.x1 - tempUvs.x0; + this.shader.uniforms.uFrame[3] = tempUvs.y2 - tempUvs.y0; - this.shader.uniforms.uTransform.value[0] = (this.tilePosition.x % (tempWidth * this.tileScale.x)) / this._width; - this.shader.uniforms.uTransform.value[1] = (this.tilePosition.y % (tempHeight * this.tileScale.y)) / this._height; - this.shader.uniforms.uTransform.value[2] = ( tw / this._width ) * this.tileScale.x; - this.shader.uniforms.uTransform.value[3] = ( th / this._height ) * this.tileScale.y; + this.shader.uniforms.uTransform[0] = (this.tilePosition.x % (tempWidth * this.tileScale.x)) / this._width; + this.shader.uniforms.uTransform[1] = (this.tilePosition.y % (tempHeight * this.tileScale.y)) / this._height; + this.shader.uniforms.uTransform[2] = ( tw / this._width ) * this.tileScale.x; + this.shader.uniforms.uTransform[3] = ( th / this._height ) * this.tileScale.y; - renderer.setObjectRenderer(renderer.plugins.sprite); - renderer.plugins.sprite.render(this); + this.caclulateVertices(); + + renderer.bindShader(this.shader); + + this.vertexBuffer.upload(this.interleaved); + this.indexBuffer.upload(this.indices); + + this.vao.bind() + .draw(this.gl.TRIANGLES, 6 ) + .unbind(); + // renderer.plugins.sprite.render(this); texture._uvs = tempUvs; texture._frame.width = tempWidth; @@ -22485,6 +22579,52 @@ //context.scale(1 / this.tileScale.x, 1 / this.tileScale.y); }; +TilingSprite.prototype.caclulateVertices = function () +{ + var texture = this._texture, + wt = this.transform.worldTransform, + a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty, + vertexData = this.interleaved, + w0, w1, h0, h1, + trim = texture.trim, + crop = texture.crop; + + + if (trim) + { + // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. + w1 = trim.x - this.anchor.x * crop.width; + w0 = w1 + trim.width; + + h1 = trim.y - this.anchor.y * crop.height; + h0 = h1 + trim.height; + + } + else + { + w0 = (crop.width ) * (1-this.anchor.x); + w1 = (crop.width ) * -this.anchor.x; + + h0 = crop.height * (1-this.anchor.y); + h1 = crop.height * -this.anchor.y; + } + + // xy + vertexData[0] = a * w1 + c * h1 + tx; + vertexData[1] = d * h1 + b * w1 + ty; + + // xy + vertexData[2] = a * w0 + c * h1 + tx; + vertexData[3] = d * h1 + b * w0 + ty; + + // xy + vertexData[4] = a * w0 + c * h0 + tx; + vertexData[5] = d * h0 + b * w0 + ty; + + // xy + vertexData[6] = a * w1 + c * h0 + tx; + vertexData[7] = d * h0 + b * w1 + ty; +}; /** * Returns the framing rectangle of the sprite as a Rectangle object @@ -22593,7 +22733,7 @@ * */ TilingSprite.prototype.destroy = function () { - core.Sprite.prototype.destroy.call(this); + Sprite.prototype.destroy.call(this); this.tileScale = null; this._tileScaleOffset = null; @@ -22641,7 +22781,7 @@ return new TilingSprite(core.Texture.fromImage(imageId, crossorigin, scaleMode),width,height); }; -},{"../core":56,"../core/sprites/canvas/CanvasTinter":90}],109:[function(require,module,exports){ +},{"../core":56,"../core/sprites/Sprite":88,"../core/sprites/canvas/CanvasTinter":90,"../core/utils/createIndicesForQuads":102,"pixi-gl-core":14}],109:[function(require,module,exports){ var core = require('../core'), DisplayObject = core.DisplayObject, _tempMatrix = new core.Matrix(); @@ -24301,7 +24441,7 @@ global.PIXI = core; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./accessibility":38,"./core":56,"./deprecation":105,"./extras":112,"./filters":122,"./interaction":127,"./loaders":130,"./polyfill":142}],125:[function(require,module,exports){ +},{"./accessibility":38,"./core":56,"./deprecation":105,"./extras":112,"./filters":122,"./interaction":127,"./loaders":130,"./polyfill":141}],125:[function(require,module,exports){ var core = require('../core'); /** @@ -26451,10 +26591,10 @@ Plane: require('./Plane'), Rope: require('./Rope'), MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') + // MeshShader: require('./webgl/MeshShader') }; -},{"./Mesh":134,"./Plane":135,"./Rope":136,"./webgl/MeshRenderer":138,"./webgl/MeshShader":139}],138:[function(require,module,exports){ +},{"./Mesh":134,"./Plane":135,"./Rope":136,"./webgl/MeshRenderer":138}],138:[function(require,module,exports){ var core = require('../../core'), Mesh = require('../Mesh'); @@ -26684,66 +26824,6 @@ }; },{"../../core":56,"../Mesh":134}],139:[function(require,module,exports){ -var core = require('../../core'); - -/** - * @class - * @extends PIXI.Shader - * @memberof PIXI.mesh - * @param shaderManager {PIXI.ShaderManager} The WebGL shader manager this shader works for. - */ -function MeshShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -MeshShader.prototype = Object.create(core.Shader.prototype); -MeshShader.prototype.constructor = MeshShader; -module.exports = MeshShader; - - -},{"../../core":56}],140:[function(require,module,exports){ // References: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign @@ -26759,7 +26839,7 @@ }; } -},{}],141:[function(require,module,exports){ +},{}],140:[function(require,module,exports){ // References: // https://github.com/sindresorhus/object-assign // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign @@ -26769,12 +26849,12 @@ Object.assign = require('object-assign'); } -},{"object-assign":13}],142:[function(require,module,exports){ +},{"object-assign":13}],141:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); -},{"./Math.sign":140,"./Object.assign":141,"./requestAnimationFrame":143}],143:[function(require,module,exports){ +},{"./Math.sign":139,"./Object.assign":140,"./requestAnimationFrame":142}],142:[function(require,module,exports){ (function (global){ // References: // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ diff --git a/bin/pixi.js b/bin/pixi.js index bac9e3b..a94735c 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -4616,7 +4616,7 @@ function VertexArrayObject(gl) { - + this.nativeVaoExtension = ( gl.getExtension('OES_vertex_array_object') || gl.getExtension('MOZ_OES_vertex_array_object') || @@ -4627,7 +4627,7 @@ if(this.nativeVaoExtension) { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); } this.gl = gl; @@ -4638,7 +4638,7 @@ this.dirty = false; - + } VertexArrayObject.prototype.constructor = VertexArrayObject; @@ -4648,7 +4648,7 @@ { if(this.nativeVao) { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); if(this.dirty) { @@ -4678,18 +4678,18 @@ { var gl = this.gl; - for (var i = 0; i < this.attributes.length; i++) + for (var i = 0; i < this.attributes.length; i++) { var attrib = this.attributes[i]; - attrib.buffer.bind(); + attrib.buffer.bind(); - //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); + //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); gl.vertexAttribPointer(attrib.attribute.location, - attrib.attribute.size, attrib.type || gl.FLOAT, - attrib.normalized || false, - attrib.stride || 0, + attrib.attribute.size, attrib.type || gl.FLOAT, + attrib.normalized || false, + attrib.stride || 0, attrib.start || 0); - + gl.enableVertexAttribArray(attrib.attribute.location); }; @@ -4732,10 +4732,10 @@ // for now, no but lets see what happens in the real world! if(this.nativeVao) { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); } - for (var i = 0; i < this.attributes.length; i++) + for (var i = 0; i < this.attributes.length; i++) { var attrib = this.attributes[i]; gl.disableVertexAttribArray(attrib.attribute.location); @@ -4743,7 +4743,7 @@ this.attributes.length = 0; this.indexBuffer = null; - + return this; } @@ -4755,7 +4755,6 @@ return this; } - },{}],20:[function(require,module,exports){ /** @@ -11513,6 +11512,8 @@ .addIndex(this.indexBuffer) .addAttribute(this.buffer, shader.attributes.aVertexPosition, gl.FLOAT, false, 4 * 6, 0) .addAttribute(this.buffer, shader.attributes.aColor, gl.FLOAT, false, 4 * 6, 2 * 4); + + } WebGLGraphicsData.prototype.constructor = WebGLGraphicsData; @@ -22192,8 +22193,11 @@ },{"../core":56}],108:[function(require,module,exports){ var core = require('../core'), // a sprite use dfor rendering textures.. + Sprite = require('../core/sprites/Sprite'), tempPoint = new core.Point(), CanvasTinter = require('../core/sprites/canvas/CanvasTinter'); +var glCore = require('pixi-gl-core'), + createIndicesForQuads = require('../core/utils/createIndicesForQuads'); /** * A tiling sprite is a fast way of rendering a tiling image @@ -22207,7 +22211,23 @@ */ function TilingSprite(texture, width, height) { - core.Sprite.call(this, texture); + Sprite.call(this, texture); + + this.gl = null; + /** + * Number of values sent in the vertex buffer. + * positionX, positionY, colorR, colorG, colorB = 5 + * + * @member {number} + */ + this.vertSize = 5; + + /** + * The size of the vertex information in bytes. + * + * @member {number} + */ + this.vertByteSize = this.vertSize * 4; /** * The scaling of the image that is being tiled @@ -22253,63 +22273,40 @@ this._canvasPattern = null; //TODO move.. - this.shader = new core.Filter( - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - 'attribute vec4 aColor;', - 'uniform mat3 projectionMatrix;', - 'uniform vec4 uFrame;', - 'uniform vec4 uTransform;', + this.vertices = new Float32Array([ + -1,-1, + 1,-1, + 1,1, + -1,1 + ]); - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', + this.uvs = new Float32Array([ + 0,0, + 1,0, + 1,1, + 0,1 + ]); - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + this.interleaved = new Float32Array(8 * 2); - ' vec2 coord = aTextureCoord;', - ' coord -= uTransform.xy;', - ' coord /= uTransform.zw;', - ' vTextureCoord = coord;', + for (var i = 0; i < 4; i++) { + this.interleaved[i*4] = this.vertices[(i*2)]; + this.interleaved[(i*4)+1] = this.vertices[(i*2)+1]; + this.interleaved[(i*4)+2] = this.uvs[i*2]; + this.interleaved[(i*4)+3] = this.uvs[(i*2)+1]; + } - ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', - '}' - ].join('\n'), - [ - 'precision lowp float;', + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + this.indices = createIndicesForQuads(1); - 'varying vec2 vTextureCoord;', - 'varying vec4 vColor;', - - 'uniform sampler2D uSampler;', - 'uniform vec4 uFrame;', - 'uniform vec2 uPixelSize;', - - 'void main(void){', - - ' vec2 coord = mod(vTextureCoord, uFrame.zw);', - ' coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);', - ' coord += uFrame.xy;', - - ' gl_FragColor = texture2D(uSampler, coord) * vColor ;', - '}' - ].join('\n'), - - // set the uniforms - { - uFrame: { type: '4fv', value: [0,0,1,1] }, - uTransform: { type: '4fv', value: [0,0,1,1] }, - uPixelSize : { type : '2fv', value: [1, 1]} - } - ); } -TilingSprite.prototype = Object.create(core.Sprite.prototype); +TilingSprite.prototype = Object.create(Sprite.prototype); TilingSprite.prototype.constructor = TilingSprite; module.exports = TilingSprite; @@ -22355,6 +22352,82 @@ return; }; +TilingSprite.prototype.initShader = function (gl) +{ + this.gl = gl; + this.shader = new glCore.GLShader(gl, + [ + 'precision lowp float;', + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + 'attribute vec4 aColor;', + + 'uniform mat3 projectionMatrix;', + + 'uniform vec4 uFrame;', + 'uniform vec4 uTransform;', + + 'varying vec2 vTextureCoord;', + 'varying vec4 vColor;', + + 'void main(void){', + ' gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + + ' vec2 coord = aTextureCoord;', + ' coord -= uTransform.xy;', + ' coord /= uTransform.zw;', + ' vTextureCoord = coord;', + + ' vColor = vec4(aColor.rgb * aColor.a, aColor.a);', + '}' + ].join('\n'), + [ + 'precision lowp float;', + + 'varying vec2 vTextureCoord;', + 'varying vec4 vColor;', + + 'uniform sampler2D uSampler;', + 'uniform vec4 uFrame;', + 'uniform vec2 uPixelSize;', + + 'void main(void){', + + ' vec2 coord = mod(vTextureCoord, uFrame.zw);', + ' coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);', + ' coord += uFrame.xy;', + + // ' gl_FragColor = texture2D(uSampler, coord) * vColor ;', + ' gl_FragColor = vec4(1.0);', + '}' + ].join('\n')/*8, + + // set the uniforms + { + uFrame: { type: '4fv', value: [0,0,1,1] }, + uTransform: { type: '4fv', value: [0,0,1,1] }, + uPixelSize : { type : '2fv', value: [1, 1]} + }*/ + ); + + /* + * @member {WebGLBuffer} The vertex buffer + */ + + this.vertexBuffer = glCore.GLBuffer.createVertexBuffer(this.gl, this.interleaved); + this.indexBuffer = glCore.GLBuffer.createIndexBuffer(this.gl, this.indices); + + this.vertexBuffer.upload(this.interleaved); + this.indexBuffer.upload(this.indices); + + this.vao = new glCore.VertexArrayObject(gl); + + this.vao.addIndex(this.indexBuffer) + .addAttribute(this.vertexBuffer, this.shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) + .addAttribute(this.vertexBuffer, this.shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) + .addAttribute(this.vertexBuffer, this.shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4); + // .addAttribute(this.vertexBuffer, this.shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); +}; /** * Renders the object using the WebGL renderer @@ -22367,11 +22440,23 @@ // tweak our texture temporarily.. var texture = this._texture; + + // render VertexArrayObject + + if(!texture || !texture._uvs) { return; } + if(!this.inited) + { + this.initShader(renderer.gl); + this.inited = true; + // create VertexArrayObject; + // create shader + } + var tempUvs = texture._uvs, tempWidth = texture._frame.width, tempHeight = texture._frame.height, @@ -22382,21 +22467,30 @@ texture._frame.width = this.width; texture._frame.height = this.height; - this.shader.uniforms.uPixelSize.value[0] = 1.0/tw; - this.shader.uniforms.uPixelSize.value[1] = 1.0/th; + this.shader.uniforms.uPixelSize[0] = 1.0/tw; + this.shader.uniforms.uPixelSize[1] = 1.0/th; - this.shader.uniforms.uFrame.value[0] = tempUvs.x0; - this.shader.uniforms.uFrame.value[1] = tempUvs.y0; - this.shader.uniforms.uFrame.value[2] = tempUvs.x1 - tempUvs.x0; - this.shader.uniforms.uFrame.value[3] = tempUvs.y2 - tempUvs.y0; + this.shader.uniforms.uFrame[0] = tempUvs.x0; + this.shader.uniforms.uFrame[1] = tempUvs.y0; + this.shader.uniforms.uFrame[2] = tempUvs.x1 - tempUvs.x0; + this.shader.uniforms.uFrame[3] = tempUvs.y2 - tempUvs.y0; - this.shader.uniforms.uTransform.value[0] = (this.tilePosition.x % (tempWidth * this.tileScale.x)) / this._width; - this.shader.uniforms.uTransform.value[1] = (this.tilePosition.y % (tempHeight * this.tileScale.y)) / this._height; - this.shader.uniforms.uTransform.value[2] = ( tw / this._width ) * this.tileScale.x; - this.shader.uniforms.uTransform.value[3] = ( th / this._height ) * this.tileScale.y; + this.shader.uniforms.uTransform[0] = (this.tilePosition.x % (tempWidth * this.tileScale.x)) / this._width; + this.shader.uniforms.uTransform[1] = (this.tilePosition.y % (tempHeight * this.tileScale.y)) / this._height; + this.shader.uniforms.uTransform[2] = ( tw / this._width ) * this.tileScale.x; + this.shader.uniforms.uTransform[3] = ( th / this._height ) * this.tileScale.y; - renderer.setObjectRenderer(renderer.plugins.sprite); - renderer.plugins.sprite.render(this); + this.caclulateVertices(); + + renderer.bindShader(this.shader); + + this.vertexBuffer.upload(this.interleaved); + this.indexBuffer.upload(this.indices); + + this.vao.bind() + .draw(this.gl.TRIANGLES, 6 ) + .unbind(); + // renderer.plugins.sprite.render(this); texture._uvs = tempUvs; texture._frame.width = tempWidth; @@ -22485,6 +22579,52 @@ //context.scale(1 / this.tileScale.x, 1 / this.tileScale.y); }; +TilingSprite.prototype.caclulateVertices = function () +{ + var texture = this._texture, + wt = this.transform.worldTransform, + a = wt.a, b = wt.b, c = wt.c, d = wt.d, tx = wt.tx, ty = wt.ty, + vertexData = this.interleaved, + w0, w1, h0, h1, + trim = texture.trim, + crop = texture.crop; + + + if (trim) + { + // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. + w1 = trim.x - this.anchor.x * crop.width; + w0 = w1 + trim.width; + + h1 = trim.y - this.anchor.y * crop.height; + h0 = h1 + trim.height; + + } + else + { + w0 = (crop.width ) * (1-this.anchor.x); + w1 = (crop.width ) * -this.anchor.x; + + h0 = crop.height * (1-this.anchor.y); + h1 = crop.height * -this.anchor.y; + } + + // xy + vertexData[0] = a * w1 + c * h1 + tx; + vertexData[1] = d * h1 + b * w1 + ty; + + // xy + vertexData[2] = a * w0 + c * h1 + tx; + vertexData[3] = d * h1 + b * w0 + ty; + + // xy + vertexData[4] = a * w0 + c * h0 + tx; + vertexData[5] = d * h0 + b * w0 + ty; + + // xy + vertexData[6] = a * w1 + c * h0 + tx; + vertexData[7] = d * h0 + b * w1 + ty; +}; /** * Returns the framing rectangle of the sprite as a Rectangle object @@ -22593,7 +22733,7 @@ * */ TilingSprite.prototype.destroy = function () { - core.Sprite.prototype.destroy.call(this); + Sprite.prototype.destroy.call(this); this.tileScale = null; this._tileScaleOffset = null; @@ -22641,7 +22781,7 @@ return new TilingSprite(core.Texture.fromImage(imageId, crossorigin, scaleMode),width,height); }; -},{"../core":56,"../core/sprites/canvas/CanvasTinter":90}],109:[function(require,module,exports){ +},{"../core":56,"../core/sprites/Sprite":88,"../core/sprites/canvas/CanvasTinter":90,"../core/utils/createIndicesForQuads":102,"pixi-gl-core":14}],109:[function(require,module,exports){ var core = require('../core'), DisplayObject = core.DisplayObject, _tempMatrix = new core.Matrix(); @@ -24301,7 +24441,7 @@ global.PIXI = core; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./accessibility":38,"./core":56,"./deprecation":105,"./extras":112,"./filters":122,"./interaction":127,"./loaders":130,"./polyfill":142}],125:[function(require,module,exports){ +},{"./accessibility":38,"./core":56,"./deprecation":105,"./extras":112,"./filters":122,"./interaction":127,"./loaders":130,"./polyfill":141}],125:[function(require,module,exports){ var core = require('../core'); /** @@ -26451,10 +26591,10 @@ Plane: require('./Plane'), Rope: require('./Rope'), MeshRenderer: require('./webgl/MeshRenderer'), - MeshShader: require('./webgl/MeshShader') + // MeshShader: require('./webgl/MeshShader') }; -},{"./Mesh":134,"./Plane":135,"./Rope":136,"./webgl/MeshRenderer":138,"./webgl/MeshShader":139}],138:[function(require,module,exports){ +},{"./Mesh":134,"./Plane":135,"./Rope":136,"./webgl/MeshRenderer":138}],138:[function(require,module,exports){ var core = require('../../core'), Mesh = require('../Mesh'); @@ -26684,66 +26824,6 @@ }; },{"../../core":56,"../Mesh":134}],139:[function(require,module,exports){ -var core = require('../../core'); - -/** - * @class - * @extends PIXI.Shader - * @memberof PIXI.mesh - * @param shaderManager {PIXI.ShaderManager} The WebGL shader manager this shader works for. - */ -function MeshShader(shaderManager) -{ - core.Shader.call(this, - shaderManager, - // vertex shader - [ - 'precision lowp float;', - 'attribute vec2 aVertexPosition;', - 'attribute vec2 aTextureCoord;', - - 'uniform mat3 translationMatrix;', - 'uniform mat3 projectionMatrix;', - - 'varying vec2 vTextureCoord;', - - 'void main(void){', - ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', - ' vTextureCoord = aTextureCoord;', - '}' - ].join('\n'), - [ - 'precision lowp float;', - - 'varying vec2 vTextureCoord;', - 'uniform float alpha;', - - 'uniform sampler2D uSampler;', - - 'void main(void){', - ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', - '}' - ].join('\n'), - // custom uniforms - { - alpha: { type: '1f', value: 0 }, - translationMatrix: { type: 'mat3', value: new Float32Array(9) }, - projectionMatrix: { type: 'mat3', value: new Float32Array(9) } - }, - // custom attributes - { - aVertexPosition:0, - aTextureCoord:0 - } - ); -} - -MeshShader.prototype = Object.create(core.Shader.prototype); -MeshShader.prototype.constructor = MeshShader; -module.exports = MeshShader; - - -},{"../../core":56}],140:[function(require,module,exports){ // References: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign @@ -26759,7 +26839,7 @@ }; } -},{}],141:[function(require,module,exports){ +},{}],140:[function(require,module,exports){ // References: // https://github.com/sindresorhus/object-assign // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign @@ -26769,12 +26849,12 @@ Object.assign = require('object-assign'); } -},{"object-assign":13}],142:[function(require,module,exports){ +},{"object-assign":13}],141:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); -},{"./Math.sign":140,"./Object.assign":141,"./requestAnimationFrame":143}],143:[function(require,module,exports){ +},{"./Math.sign":139,"./Object.assign":140,"./requestAnimationFrame":142}],142:[function(require,module,exports){ (function (global){ // References: // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ diff --git a/bin/pixi.js.map b/bin/pixi.js.map index ffc024e..940641c 100644 --- a/bin/pixi.js.map +++ b/bin/pixi.js.map @@ -1 +1 @@ -{"version":3,"names":[],"mappings":"","sources":["pixi.js"],"sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.PIXI = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= 0 &&\n arr.length % 1 === 0\n );\n }\n\n function _arrayEach(arr, iterator) {\n var index = -1,\n length = arr.length;\n\n while (++index < length) {\n iterator(arr[index], index, arr);\n }\n }\n\n function _map(arr, iterator) {\n var index = -1,\n length = arr.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iterator(arr[index], index, arr);\n }\n return result;\n }\n\n function _range(count) {\n return _map(Array(count), function (v, i) { return i; });\n }\n\n function _reduce(arr, iterator, memo) {\n _arrayEach(arr, function (x, i, a) {\n memo = iterator(memo, x, i, a);\n });\n return memo;\n }\n\n function _forEachOf(object, iterator) {\n _arrayEach(_keys(object), function (key) {\n iterator(object[key], key);\n });\n }\n\n function _indexOf(arr, item) {\n for (var i = 0; i < arr.length; i++) {\n if (arr[i] === item) return i;\n }\n return -1;\n }\n\n var _keys = Object.keys || function (obj) {\n var keys = [];\n for (var k in obj) {\n if (obj.hasOwnProperty(k)) {\n keys.push(k);\n }\n }\n return keys;\n };\n\n function _keyIterator(coll) {\n var i = -1;\n var len;\n var keys;\n if (_isArrayLike(coll)) {\n len = coll.length;\n return function next() {\n i++;\n return i < len ? i : null;\n };\n } else {\n keys = _keys(coll);\n len = keys.length;\n return function next() {\n i++;\n return i < len ? keys[i] : null;\n };\n }\n }\n\n // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)\n // This accumulates the arguments passed into an array, after a given index.\n // From underscore.js (https://github.com/jashkenas/underscore/pull/2140).\n function _restParam(func, startIndex) {\n startIndex = startIndex == null ? func.length - 1 : +startIndex;\n return function() {\n var length = Math.max(arguments.length - startIndex, 0);\n var rest = Array(length);\n for (var index = 0; index < length; index++) {\n rest[index] = arguments[index + startIndex];\n }\n switch (startIndex) {\n case 0: return func.call(this, rest);\n case 1: return func.call(this, arguments[0], rest);\n }\n // Currently unused but handle cases outside of the switch statement:\n // var args = Array(startIndex + 1);\n // for (index = 0; index < startIndex; index++) {\n // args[index] = arguments[index];\n // }\n // args[startIndex] = rest;\n // return func.apply(this, args);\n };\n }\n\n function _withoutIndex(iterator) {\n return function (value, index, callback) {\n return iterator(value, callback);\n };\n }\n\n //// exported async module functions ////\n\n //// nextTick implementation with browser-compatible fallback ////\n\n // capture the global reference to guard against fakeTimer mocks\n var _setImmediate = typeof setImmediate === 'function' && setImmediate;\n\n var _delay = _setImmediate ? function(fn) {\n // not a direct alias for IE10 compatibility\n _setImmediate(fn);\n } : function(fn) {\n setTimeout(fn, 0);\n };\n\n if (typeof process === 'object' && typeof process.nextTick === 'function') {\n async.nextTick = process.nextTick;\n } else {\n async.nextTick = _delay;\n }\n async.setImmediate = _setImmediate ? _delay : async.nextTick;\n\n\n async.forEach =\n async.each = function (arr, iterator, callback) {\n return async.eachOf(arr, _withoutIndex(iterator), callback);\n };\n\n async.forEachSeries =\n async.eachSeries = function (arr, iterator, callback) {\n return async.eachOfSeries(arr, _withoutIndex(iterator), callback);\n };\n\n\n async.forEachLimit =\n async.eachLimit = function (arr, limit, iterator, callback) {\n return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);\n };\n\n async.forEachOf =\n async.eachOf = function (object, iterator, callback) {\n callback = _once(callback || noop);\n object = object || [];\n\n var iter = _keyIterator(object);\n var key, completed = 0;\n\n while ((key = iter()) != null) {\n completed += 1;\n iterator(object[key], key, only_once(done));\n }\n\n if (completed === 0) callback(null);\n\n function done(err) {\n completed--;\n if (err) {\n callback(err);\n }\n // Check key is null in case iterator isn't exhausted\n // and done resolved synchronously.\n else if (key === null && completed <= 0) {\n callback(null);\n }\n }\n };\n\n async.forEachOfSeries =\n async.eachOfSeries = function (obj, iterator, callback) {\n callback = _once(callback || noop);\n obj = obj || [];\n var nextKey = _keyIterator(obj);\n var key = nextKey();\n function iterate() {\n var sync = true;\n if (key === null) {\n return callback(null);\n }\n iterator(obj[key], key, only_once(function (err) {\n if (err) {\n callback(err);\n }\n else {\n key = nextKey();\n if (key === null) {\n return callback(null);\n } else {\n if (sync) {\n async.setImmediate(iterate);\n } else {\n iterate();\n }\n }\n }\n }));\n sync = false;\n }\n iterate();\n };\n\n\n\n async.forEachOfLimit =\n async.eachOfLimit = function (obj, limit, iterator, callback) {\n _eachOfLimit(limit)(obj, iterator, callback);\n };\n\n function _eachOfLimit(limit) {\n\n return function (obj, iterator, callback) {\n callback = _once(callback || noop);\n obj = obj || [];\n var nextKey = _keyIterator(obj);\n if (limit <= 0) {\n return callback(null);\n }\n var done = false;\n var running = 0;\n var errored = false;\n\n (function replenish () {\n if (done && running <= 0) {\n return callback(null);\n }\n\n while (running < limit && !errored) {\n var key = nextKey();\n if (key === null) {\n done = true;\n if (running <= 0) {\n callback(null);\n }\n return;\n }\n running += 1;\n iterator(obj[key], key, only_once(function (err) {\n running -= 1;\n if (err) {\n callback(err);\n errored = true;\n }\n else {\n replenish();\n }\n }));\n }\n })();\n };\n }\n\n\n function doParallel(fn) {\n return function (obj, iterator, callback) {\n return fn(async.eachOf, obj, iterator, callback);\n };\n }\n function doParallelLimit(fn) {\n return function (obj, limit, iterator, callback) {\n return fn(_eachOfLimit(limit), obj, iterator, callback);\n };\n }\n function doSeries(fn) {\n return function (obj, iterator, callback) {\n return fn(async.eachOfSeries, obj, iterator, callback);\n };\n }\n\n function _asyncMap(eachfn, arr, iterator, callback) {\n callback = _once(callback || noop);\n arr = arr || [];\n var results = _isArrayLike(arr) ? [] : {};\n eachfn(arr, function (value, index, callback) {\n iterator(value, function (err, v) {\n results[index] = v;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n\n async.map = doParallel(_asyncMap);\n async.mapSeries = doSeries(_asyncMap);\n async.mapLimit = doParallelLimit(_asyncMap);\n\n // reduce only has a series version, as doing reduce in parallel won't\n // work in many situations.\n async.inject =\n async.foldl =\n async.reduce = function (arr, memo, iterator, callback) {\n async.eachOfSeries(arr, function (x, i, callback) {\n iterator(memo, x, function (err, v) {\n memo = v;\n callback(err);\n });\n }, function (err) {\n callback(err, memo);\n });\n };\n\n async.foldr =\n async.reduceRight = function (arr, memo, iterator, callback) {\n var reversed = _map(arr, identity).reverse();\n async.reduce(reversed, memo, iterator, callback);\n };\n\n async.transform = function (arr, memo, iterator, callback) {\n if (arguments.length === 3) {\n callback = iterator;\n iterator = memo;\n memo = _isArray(arr) ? [] : {};\n }\n\n async.eachOf(arr, function(v, k, cb) {\n iterator(memo, v, k, cb);\n }, function(err) {\n callback(err, memo);\n });\n };\n\n function _filter(eachfn, arr, iterator, callback) {\n var results = [];\n eachfn(arr, function (x, index, callback) {\n iterator(x, function (v) {\n if (v) {\n results.push({index: index, value: x});\n }\n callback();\n });\n }, function () {\n callback(_map(results.sort(function (a, b) {\n return a.index - b.index;\n }), function (x) {\n return x.value;\n }));\n });\n }\n\n async.select =\n async.filter = doParallel(_filter);\n\n async.selectLimit =\n async.filterLimit = doParallelLimit(_filter);\n\n async.selectSeries =\n async.filterSeries = doSeries(_filter);\n\n function _reject(eachfn, arr, iterator, callback) {\n _filter(eachfn, arr, function(value, cb) {\n iterator(value, function(v) {\n cb(!v);\n });\n }, callback);\n }\n async.reject = doParallel(_reject);\n async.rejectLimit = doParallelLimit(_reject);\n async.rejectSeries = doSeries(_reject);\n\n function _createTester(eachfn, check, getResult) {\n return function(arr, limit, iterator, cb) {\n function done() {\n if (cb) cb(getResult(false, void 0));\n }\n function iteratee(x, _, callback) {\n if (!cb) return callback();\n iterator(x, function (v) {\n if (cb && check(v)) {\n cb(getResult(true, x));\n cb = iterator = false;\n }\n callback();\n });\n }\n if (arguments.length > 3) {\n eachfn(arr, limit, iteratee, done);\n } else {\n cb = iterator;\n iterator = limit;\n eachfn(arr, iteratee, done);\n }\n };\n }\n\n async.any =\n async.some = _createTester(async.eachOf, toBool, identity);\n\n async.someLimit = _createTester(async.eachOfLimit, toBool, identity);\n\n async.all =\n async.every = _createTester(async.eachOf, notId, notId);\n\n async.everyLimit = _createTester(async.eachOfLimit, notId, notId);\n\n function _findGetResult(v, x) {\n return x;\n }\n async.detect = _createTester(async.eachOf, identity, _findGetResult);\n async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);\n async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);\n\n async.sortBy = function (arr, iterator, callback) {\n async.map(arr, function (x, callback) {\n iterator(x, function (err, criteria) {\n if (err) {\n callback(err);\n }\n else {\n callback(null, {value: x, criteria: criteria});\n }\n });\n }, function (err, results) {\n if (err) {\n return callback(err);\n }\n else {\n callback(null, _map(results.sort(comparator), function (x) {\n return x.value;\n }));\n }\n\n });\n\n function comparator(left, right) {\n var a = left.criteria, b = right.criteria;\n return a < b ? -1 : a > b ? 1 : 0;\n }\n };\n\n async.auto = function (tasks, concurrency, callback) {\n if (typeof arguments[1] === 'function') {\n // concurrency is optional, shift the args.\n callback = concurrency;\n concurrency = null;\n }\n callback = _once(callback || noop);\n var keys = _keys(tasks);\n var remainingTasks = keys.length;\n if (!remainingTasks) {\n return callback(null);\n }\n if (!concurrency) {\n concurrency = remainingTasks;\n }\n\n var results = {};\n var runningTasks = 0;\n\n var hasError = false;\n\n var listeners = [];\n function addListener(fn) {\n listeners.unshift(fn);\n }\n function removeListener(fn) {\n var idx = _indexOf(listeners, fn);\n if (idx >= 0) listeners.splice(idx, 1);\n }\n function taskComplete() {\n remainingTasks--;\n _arrayEach(listeners.slice(0), function (fn) {\n fn();\n });\n }\n\n addListener(function () {\n if (!remainingTasks) {\n callback(null, results);\n }\n });\n\n _arrayEach(keys, function (k) {\n if (hasError) return;\n var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];\n var taskCallback = _restParam(function(err, args) {\n runningTasks--;\n if (args.length <= 1) {\n args = args[0];\n }\n if (err) {\n var safeResults = {};\n _forEachOf(results, function(val, rkey) {\n safeResults[rkey] = val;\n });\n safeResults[k] = args;\n hasError = true;\n\n callback(err, safeResults);\n }\n else {\n results[k] = args;\n async.setImmediate(taskComplete);\n }\n });\n var requires = task.slice(0, task.length - 1);\n // prevent dead-locks\n var len = requires.length;\n var dep;\n while (len--) {\n if (!(dep = tasks[requires[len]])) {\n throw new Error('Has nonexistent dependency in ' + requires.join(', '));\n }\n if (_isArray(dep) && _indexOf(dep, k) >= 0) {\n throw new Error('Has cyclic dependencies');\n }\n }\n function ready() {\n return runningTasks < concurrency && _reduce(requires, function (a, x) {\n return (a && results.hasOwnProperty(x));\n }, true) && !results.hasOwnProperty(k);\n }\n if (ready()) {\n runningTasks++;\n task[task.length - 1](taskCallback, results);\n }\n else {\n addListener(listener);\n }\n function listener() {\n if (ready()) {\n runningTasks++;\n removeListener(listener);\n task[task.length - 1](taskCallback, results);\n }\n }\n });\n };\n\n\n\n async.retry = function(times, task, callback) {\n var DEFAULT_TIMES = 5;\n var DEFAULT_INTERVAL = 0;\n\n var attempts = [];\n\n var opts = {\n times: DEFAULT_TIMES,\n interval: DEFAULT_INTERVAL\n };\n\n function parseTimes(acc, t){\n if(typeof t === 'number'){\n acc.times = parseInt(t, 10) || DEFAULT_TIMES;\n } else if(typeof t === 'object'){\n acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;\n acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;\n } else {\n throw new Error('Unsupported argument type for \\'times\\': ' + typeof t);\n }\n }\n\n var length = arguments.length;\n if (length < 1 || length > 3) {\n throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');\n } else if (length <= 2 && typeof times === 'function') {\n callback = task;\n task = times;\n }\n if (typeof times !== 'function') {\n parseTimes(opts, times);\n }\n opts.callback = callback;\n opts.task = task;\n\n function wrappedTask(wrappedCallback, wrappedResults) {\n function retryAttempt(task, finalAttempt) {\n return function(seriesCallback) {\n task(function(err, result){\n seriesCallback(!err || finalAttempt, {err: err, result: result});\n }, wrappedResults);\n };\n }\n\n function retryInterval(interval){\n return function(seriesCallback){\n setTimeout(function(){\n seriesCallback(null);\n }, interval);\n };\n }\n\n while (opts.times) {\n\n var finalAttempt = !(opts.times-=1);\n attempts.push(retryAttempt(opts.task, finalAttempt));\n if(!finalAttempt && opts.interval > 0){\n attempts.push(retryInterval(opts.interval));\n }\n }\n\n async.series(attempts, function(done, data){\n data = data[data.length - 1];\n (wrappedCallback || opts.callback)(data.err, data.result);\n });\n }\n\n // If a callback is passed, run this as a controll flow\n return opts.callback ? wrappedTask() : wrappedTask;\n };\n\n async.waterfall = function (tasks, callback) {\n callback = _once(callback || noop);\n if (!_isArray(tasks)) {\n var err = new Error('First argument to waterfall must be an array of functions');\n return callback(err);\n }\n if (!tasks.length) {\n return callback();\n }\n function wrapIterator(iterator) {\n return _restParam(function (err, args) {\n if (err) {\n callback.apply(null, [err].concat(args));\n }\n else {\n var next = iterator.next();\n if (next) {\n args.push(wrapIterator(next));\n }\n else {\n args.push(callback);\n }\n ensureAsync(iterator).apply(null, args);\n }\n });\n }\n wrapIterator(async.iterator(tasks))();\n };\n\n function _parallel(eachfn, tasks, callback) {\n callback = callback || noop;\n var results = _isArrayLike(tasks) ? [] : {};\n\n eachfn(tasks, function (task, key, callback) {\n task(_restParam(function (err, args) {\n if (args.length <= 1) {\n args = args[0];\n }\n results[key] = args;\n callback(err);\n }));\n }, function (err) {\n callback(err, results);\n });\n }\n\n async.parallel = function (tasks, callback) {\n _parallel(async.eachOf, tasks, callback);\n };\n\n async.parallelLimit = function(tasks, limit, callback) {\n _parallel(_eachOfLimit(limit), tasks, callback);\n };\n\n async.series = function(tasks, callback) {\n _parallel(async.eachOfSeries, tasks, callback);\n };\n\n async.iterator = function (tasks) {\n function makeCallback(index) {\n function fn() {\n if (tasks.length) {\n tasks[index].apply(null, arguments);\n }\n return fn.next();\n }\n fn.next = function () {\n return (index < tasks.length - 1) ? makeCallback(index + 1): null;\n };\n return fn;\n }\n return makeCallback(0);\n };\n\n async.apply = _restParam(function (fn, args) {\n return _restParam(function (callArgs) {\n return fn.apply(\n null, args.concat(callArgs)\n );\n });\n });\n\n function _concat(eachfn, arr, fn, callback) {\n var result = [];\n eachfn(arr, function (x, index, cb) {\n fn(x, function (err, y) {\n result = result.concat(y || []);\n cb(err);\n });\n }, function (err) {\n callback(err, result);\n });\n }\n async.concat = doParallel(_concat);\n async.concatSeries = doSeries(_concat);\n\n async.whilst = function (test, iterator, callback) {\n callback = callback || noop;\n if (test()) {\n var next = _restParam(function(err, args) {\n if (err) {\n callback(err);\n } else if (test.apply(this, args)) {\n iterator(next);\n } else {\n callback.apply(null, [null].concat(args));\n }\n });\n iterator(next);\n } else {\n callback(null);\n }\n };\n\n async.doWhilst = function (iterator, test, callback) {\n var calls = 0;\n return async.whilst(function() {\n return ++calls <= 1 || test.apply(this, arguments);\n }, iterator, callback);\n };\n\n async.until = function (test, iterator, callback) {\n return async.whilst(function() {\n return !test.apply(this, arguments);\n }, iterator, callback);\n };\n\n async.doUntil = function (iterator, test, callback) {\n return async.doWhilst(iterator, function() {\n return !test.apply(this, arguments);\n }, callback);\n };\n\n async.during = function (test, iterator, callback) {\n callback = callback || noop;\n\n var next = _restParam(function(err, args) {\n if (err) {\n callback(err);\n } else {\n args.push(check);\n test.apply(this, args);\n }\n });\n\n var check = function(err, truth) {\n if (err) {\n callback(err);\n } else if (truth) {\n iterator(next);\n } else {\n callback(null);\n }\n };\n\n test(check);\n };\n\n async.doDuring = function (iterator, test, callback) {\n var calls = 0;\n async.during(function(next) {\n if (calls++ < 1) {\n next(null, true);\n } else {\n test.apply(this, arguments);\n }\n }, iterator, callback);\n };\n\n function _queue(worker, concurrency, payload) {\n if (concurrency == null) {\n concurrency = 1;\n }\n else if(concurrency === 0) {\n throw new Error('Concurrency must not be zero');\n }\n function _insert(q, data, pos, callback) {\n if (callback != null && typeof callback !== \"function\") {\n throw new Error(\"task callback must be a function\");\n }\n q.started = true;\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length === 0 && q.idle()) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n q.drain();\n });\n }\n _arrayEach(data, function(task) {\n var item = {\n data: task,\n callback: callback || noop\n };\n\n if (pos) {\n q.tasks.unshift(item);\n } else {\n q.tasks.push(item);\n }\n\n if (q.tasks.length === q.concurrency) {\n q.saturated();\n }\n });\n async.setImmediate(q.process);\n }\n function _next(q, tasks) {\n return function(){\n workers -= 1;\n\n var removed = false;\n var args = arguments;\n _arrayEach(tasks, function (task) {\n _arrayEach(workersList, function (worker, index) {\n if (worker === task && !removed) {\n workersList.splice(index, 1);\n removed = true;\n }\n });\n\n task.callback.apply(task, args);\n });\n if (q.tasks.length + workers === 0) {\n q.drain();\n }\n q.process();\n };\n }\n\n var workers = 0;\n var workersList = [];\n var q = {\n tasks: [],\n concurrency: concurrency,\n payload: payload,\n saturated: noop,\n empty: noop,\n drain: noop,\n started: false,\n paused: false,\n push: function (data, callback) {\n _insert(q, data, false, callback);\n },\n kill: function () {\n q.drain = noop;\n q.tasks = [];\n },\n unshift: function (data, callback) {\n _insert(q, data, true, callback);\n },\n process: function () {\n while(!q.paused && workers < q.concurrency && q.tasks.length){\n\n var tasks = q.payload ?\n q.tasks.splice(0, q.payload) :\n q.tasks.splice(0, q.tasks.length);\n\n var data = _map(tasks, function (task) {\n return task.data;\n });\n\n if (q.tasks.length === 0) {\n q.empty();\n }\n workers += 1;\n workersList.push(tasks[0]);\n var cb = only_once(_next(q, tasks));\n worker(data, cb);\n }\n },\n length: function () {\n return q.tasks.length;\n },\n running: function () {\n return workers;\n },\n workersList: function () {\n return workersList;\n },\n idle: function() {\n return q.tasks.length + workers === 0;\n },\n pause: function () {\n q.paused = true;\n },\n resume: function () {\n if (q.paused === false) { return; }\n q.paused = false;\n var resumeCount = Math.min(q.concurrency, q.tasks.length);\n // Need to call q.process once per concurrent\n // worker to preserve full concurrency after pause\n for (var w = 1; w <= resumeCount; w++) {\n async.setImmediate(q.process);\n }\n }\n };\n return q;\n }\n\n async.queue = function (worker, concurrency) {\n var q = _queue(function (items, cb) {\n worker(items[0], cb);\n }, concurrency, 1);\n\n return q;\n };\n\n async.priorityQueue = function (worker, concurrency) {\n\n function _compareTasks(a, b){\n return a.priority - b.priority;\n }\n\n function _binarySearch(sequence, item, compare) {\n var beg = -1,\n end = sequence.length - 1;\n while (beg < end) {\n var mid = beg + ((end - beg + 1) >>> 1);\n if (compare(item, sequence[mid]) >= 0) {\n beg = mid;\n } else {\n end = mid - 1;\n }\n }\n return beg;\n }\n\n function _insert(q, data, priority, callback) {\n if (callback != null && typeof callback !== \"function\") {\n throw new Error(\"task callback must be a function\");\n }\n q.started = true;\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length === 0) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n q.drain();\n });\n }\n _arrayEach(data, function(task) {\n var item = {\n data: task,\n priority: priority,\n callback: typeof callback === 'function' ? callback : noop\n };\n\n q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);\n\n if (q.tasks.length === q.concurrency) {\n q.saturated();\n }\n async.setImmediate(q.process);\n });\n }\n\n // Start with a normal queue\n var q = async.queue(worker, concurrency);\n\n // Override push to accept second parameter representing priority\n q.push = function (data, priority, callback) {\n _insert(q, data, priority, callback);\n };\n\n // Remove unshift function\n delete q.unshift;\n\n return q;\n };\n\n async.cargo = function (worker, payload) {\n return _queue(worker, 1, payload);\n };\n\n function _console_fn(name) {\n return _restParam(function (fn, args) {\n fn.apply(null, args.concat([_restParam(function (err, args) {\n if (typeof console === 'object') {\n if (err) {\n if (console.error) {\n console.error(err);\n }\n }\n else if (console[name]) {\n _arrayEach(args, function (x) {\n console[name](x);\n });\n }\n }\n })]));\n });\n }\n async.log = _console_fn('log');\n async.dir = _console_fn('dir');\n /*async.info = _console_fn('info');\n async.warn = _console_fn('warn');\n async.error = _console_fn('error');*/\n\n async.memoize = function (fn, hasher) {\n var memo = {};\n var queues = {};\n var has = Object.prototype.hasOwnProperty;\n hasher = hasher || identity;\n var memoized = _restParam(function memoized(args) {\n var callback = args.pop();\n var key = hasher.apply(null, args);\n if (has.call(memo, key)) { \n async.setImmediate(function () {\n callback.apply(null, memo[key]);\n });\n }\n else if (has.call(queues, key)) {\n queues[key].push(callback);\n }\n else {\n queues[key] = [callback];\n fn.apply(null, args.concat([_restParam(function (args) {\n memo[key] = args;\n var q = queues[key];\n delete queues[key];\n for (var i = 0, l = q.length; i < l; i++) {\n q[i].apply(null, args);\n }\n })]));\n }\n });\n memoized.memo = memo;\n memoized.unmemoized = fn;\n return memoized;\n };\n\n async.unmemoize = function (fn) {\n return function () {\n return (fn.unmemoized || fn).apply(null, arguments);\n };\n };\n\n function _times(mapper) {\n return function (count, iterator, callback) {\n mapper(_range(count), iterator, callback);\n };\n }\n\n async.times = _times(async.map);\n async.timesSeries = _times(async.mapSeries);\n async.timesLimit = function (count, limit, iterator, callback) {\n return async.mapLimit(_range(count), limit, iterator, callback);\n };\n\n async.seq = function (/* functions... */) {\n var fns = arguments;\n return _restParam(function (args) {\n var that = this;\n\n var callback = args[args.length - 1];\n if (typeof callback == 'function') {\n args.pop();\n } else {\n callback = noop;\n }\n\n async.reduce(fns, args, function (newargs, fn, cb) {\n fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {\n cb(err, nextargs);\n })]));\n },\n function (err, results) {\n callback.apply(that, [err].concat(results));\n });\n });\n };\n\n async.compose = function (/* functions... */) {\n return async.seq.apply(null, Array.prototype.reverse.call(arguments));\n };\n\n\n function _applyEach(eachfn) {\n return _restParam(function(fns, args) {\n var go = _restParam(function(args) {\n var that = this;\n var callback = args.pop();\n return eachfn(fns, function (fn, _, cb) {\n fn.apply(that, args.concat([cb]));\n },\n callback);\n });\n if (args.length) {\n return go.apply(this, args);\n }\n else {\n return go;\n }\n });\n }\n\n async.applyEach = _applyEach(async.eachOf);\n async.applyEachSeries = _applyEach(async.eachOfSeries);\n\n\n async.forever = function (fn, callback) {\n var done = only_once(callback || noop);\n var task = ensureAsync(fn);\n function next(err) {\n if (err) {\n return done(err);\n }\n task(next);\n }\n next();\n };\n\n function ensureAsync(fn) {\n return _restParam(function (args) {\n var callback = args.pop();\n args.push(function () {\n var innerArgs = arguments;\n if (sync) {\n async.setImmediate(function () {\n callback.apply(null, innerArgs);\n });\n } else {\n callback.apply(null, innerArgs);\n }\n });\n var sync = true;\n fn.apply(this, args);\n sync = false;\n });\n }\n\n async.ensureAsync = ensureAsync;\n\n async.constant = _restParam(function(values) {\n var args = [null].concat(values);\n return function (callback) {\n return callback.apply(this, args);\n };\n });\n\n async.wrapSync =\n async.asyncify = function asyncify(func) {\n return _restParam(function (args) {\n var callback = args.pop();\n var result;\n try {\n result = func.apply(this, args);\n } catch (e) {\n return callback(e);\n }\n // if result is Promise object\n if (_isObject(result) && typeof result.then === \"function\") {\n result.then(function(value) {\n callback(null, value);\n })[\"catch\"](function(err) {\n callback(err.message ? err : new Error(err));\n });\n } else {\n callback(null, result);\n }\n });\n };\n\n // Node.js\n if (typeof module === 'object' && module.exports) {\n module.exports = async;\n }\n // AMD / RequireJS\n else if (typeof define === 'function' && define.amd) {\n define([], function () {\n return async;\n });\n }\n // included directly via