diff --git a/bin/pixi.js b/bin/pixi.js index 7cd7492..79c8df2 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -1,1532 +1,4 @@ (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= data.byteLength) - { - gl.bufferSubData(this.type, offset, data); - } - else - { - gl.bufferData(this.type, data, this.drawType); - } - - this.data = data; -}; -/** - * Binds the buffer - * - */ -Buffer.prototype.bind = function() -{ - var gl = this.gl; - gl.bindBuffer(this.type, this.buffer); -}; - -Buffer.createVertexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); -}; - -Buffer.createIndexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); -}; - -Buffer.create = function(gl, type, data, drawType) -{ - return new Buffer(gl, type, drawType); -}; - -/** - * Destroys the buffer - * - */ -Buffer.prototype.destroy = function(){ - this.gl.deleteBuffer(this.buffer); -}; - -module.exports = Buffer; - -},{}],3:[function(require,module,exports){ - -var Texture = require('./GLTexture'); - -/** - * Helper class to create a webGL Framebuffer - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - */ -var Framebuffer = function(gl, width, height) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * The frame buffer - * - * @member {WebGLFramebuffer} - */ - this.framebuffer = gl.createFramebuffer(); - - /** - * The stencil buffer - * - * @member {WebGLRenderbuffer} - */ - this.stencil = null; - - /** - * The stencil buffer - * - * @member {GLTexture} - */ - this.texture = null; - - /** - * The width of the drawing area of the buffer - * - * @member {Number} - */ - this.width = width || 100; - /** - * The height of the drawing area of the buffer - * - * @member {Number} - */ - this.height = height || 100; -}; - -/** - * Adds a texture to the frame buffer - * @param texture {GLTexture} - */ -Framebuffer.prototype.enableTexture = function(texture) -{ - var gl = this.gl; - - this.texture = texture || new Texture(gl); - - this.texture.bind(); - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - this.bind(); - - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); -}; - -/** - * Initialises the stencil buffer - * @mat maybe you can come up with a better explaination - */ -Framebuffer.prototype.enableStencil = function() -{ - if(this.stencil)return; - - var gl = this.gl; - - this.stencil = gl.createRenderbuffer(); - - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - - // TODO.. this is depth AND stencil? - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); -}; - -/** - * Erases the drawing area and fills it with a colour - * @param r {Number} the red value of the clearing colour - * @param g {Number} the green value of the clearing colour - * @param b {Number} the blue value of the clearing colour - * @param a {Number} the alpha value of the clearing colour - */ -Framebuffer.prototype.clear = function( r, g, b, a ) -{ - this.bind(); - - var gl = this.gl; - - gl.clearColor(r, g, b, a); - gl.clear(gl.COLOR_BUFFER_BIT); -}; - -/** - * Binds the frame buffer to the WebGL context - */ -Framebuffer.prototype.bind = function() -{ - var gl = this.gl; - - if(this.texture) - { - this.texture.unbind(); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); -}; - -/** - * Unbinds the frame buffer to the WebGL context - */ -Framebuffer.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, null ); -}; -/** - * Resizes the drawing area of the buffer to the given width and height - * @param width {Number} the new width - * @param height {Number} the new height - */ -Framebuffer.prototype.resize = function(width, height) -{ - var gl = this.gl; - - this.width = width; - this.height = height; - - if ( this.texture ) - { - this.texture.uploadData(null, width, height); - } - - if ( this.stencil ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); - } -}; - -/** - * Destroys this buffer - */ -Framebuffer.prototype.destroy = function() -{ - var gl = this.gl; - - //TODO - if(this.texture) - { - this.texture.destroy(); - } - - gl.deleteFramebuffer(this.framebuffer); - - this.gl = null; - - this.stencil = null; - this.texture = null; -}; - -/** - * Creates a frame buffer with a texture containing the given data - * @mat can you confirm ? :) - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createRGBA = function(gl, width, height, data) -{ - var texture = Texture.fromData(gl, null, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); - - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture); - - fbo.unbind(); - - return fbo; -}; - -/** - * Creates a frame buffer with a texture containing the given data - * @mat not sure what the difference is with the method above ? - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createFloat32 = function(gl, width, height, data) -{ - // create a new texture.. - var texture = new Texture.fromData(gl, data, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); - - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture); - - fbo.unbind(); - - return fbo; -}; - -module.exports = Framebuffer; - -},{"./GLTexture":5}],4:[function(require,module,exports){ - -var compileProgram = require('./shader/compileProgram'), - extractAttributes = require('./shader/extractAttributes'), - extractUniforms = require('./shader/extractUniforms'), - generateUniformAccessObject = require('./shader/generateUniformAccessObject'); - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - */ -var Shader = function(gl, vertexSrc, fragmentSrc) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc); - - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - var uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject( gl, uniformData ); -}; -/** - * Uses this shader - */ -Shader.prototype.bind = function() -{ - this.gl.useProgram(this.program); -}; - -/** - * Destroys this shader - * TODO - */ -Shader.prototype.destroy = function() -{ - var gl = this.gl; -}; - -module.exports = Shader; - -},{"./shader/compileProgram":9,"./shader/extractAttributes":11,"./shader/extractUniforms":12,"./shader/generateUniformAccessObject":13}],5:[function(require,module,exports){ - -/** - * Helper class to create a WebGL Texture - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL context - * @param width {number} the width of the texture - * @param height {number} the height of the texture - * @param format {number} the pixel format of the texture. defaults to gl.RGBA - * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE - */ -var Texture = function(gl, width, height, format, type) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - - /** - * The WebGL texture - * - * @member {WebGLTexture} - */ - this.texture = gl.createTexture(); - - /** - * If mipmapping was used for this texture, enable and disable with enableMipmap() - * - * @member {Boolean} - */ - // some settings.. - this.mipmap = false; - - - /** - * Set to true to enable pre-multiplied alpha - * - * @member {Boolean} - */ - this.premultiplyAlpha = false; - - /** - * The width of texture - * - * @member {Number} - */ - this.width = width || 0; - /** - * The height of texture - * - * @member {Number} - */ - this.height = height || 0; - - /** - * The pixel format of the texture. defaults to gl.RGBA - * - * @member {Number} - */ - this.format = format || gl.RGBA; - - /** - * The gl type of the texture. defaults to gl.UNSIGNED_BYTE - * - * @member {Number} - */ - this.type = type || gl.UNSIGNED_BYTE; - - -}; - -/** - * Uploads this texture to the GPU - * @param source {HTMLImageElement|ImageData|HTMLVideoElement} the source image of the texture - */ -Texture.prototype.upload = function(source) -{ - this.bind(); - - var gl = this.gl; - - // if the source is a video, we need to use the videoWidth / videoHeight properties as width / height will be incorrect. - this.width = source.videoWidth || source.width; - this.height = source.videoHeight || source.height; - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); -}; - -var FLOATING_POINT_AVAILABLE = false; - -/** - * Use a data source and uploads this texture to the GPU - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.prototype.uploadData = function(data, width, height) -{ - this.bind(); - - var gl = this.gl; - - this.width = width || this.width; - this.height = height || this.height; - - if(data instanceof Float32Array) - { - if(!FLOATING_POINT_AVAILABLE) - { - var ext = gl.getExtension("OES_texture_float"); - - if(ext) - { - FLOATING_POINT_AVAILABLE = true; - } - else - { - throw new Error('floating point textures not available'); - } - } - - this.type = gl.FLOAT; - } - else - { - // TODO support for other types - this.type = gl.UNSIGNED_BYTE; - } - - - - // what type of data? - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); - -}; - -/** - * Binds the texture - * @param location {@mat} - */ -Texture.prototype.bind = function(location) -{ - var gl = this.gl; - - if(location !== undefined) - { - gl.activeTexture(gl.TEXTURE0 + location); - } - - gl.bindTexture(gl.TEXTURE_2D, this.texture); -}; - -/** - * Unbinds the texture - */ -Texture.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, null); -}; - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.minFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - if(this.mipmap) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); - } -}; - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.magFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); -}; - -/** - * Enables mipmapping - */ -Texture.prototype.enableMipmap = function() -{ - var gl = this.gl; - - this.bind(); - - this.mipmap = true; - - gl.generateMipmap(gl.TEXTURE_2D); -}; - -/** - * Enables linear filtering - */ -Texture.prototype.enableLinearScaling = function() -{ - this.minFilter(true); - this.magFilter(true); -}; - -/** - * Enables nearest neighbour interpolation - */ -Texture.prototype.enableNearestScaling = function() -{ - this.minFilter(false); - this.magFilter(false); -}; - -/** - * Enables clamping on the texture so WebGL will not repeat it - */ -Texture.prototype.enableWrapClamp = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); -}; - -/** - * Enable tiling on the texture - */ -Texture.prototype.enableWrapRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); -}; - -/** - * @mat - */ -Texture.prototype.enableWrapMirrorRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); -}; - - -/** - * Destroys this texture - */ -Texture.prototype.destroy = function() -{ - var gl = this.gl; - //TODO - gl.deleteTexture(this.texture); -}; - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param source {HTMLImageElement|ImageData} the source image of the texture - * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha - */ -Texture.fromSource = function(gl, source, premultiplyAlpha) -{ - var texture = new Texture(gl); - texture.premultiplyAlpha = premultiplyAlpha || false; - texture.upload(source); - - return texture; -}; - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.fromData = function(gl, data, width, height) -{ - //console.log(data, width, height); - var texture = new Texture(gl); - texture.uploadData(data, width, height); - - return texture; -}; - - -module.exports = Texture; - -},{}],6:[function(require,module,exports){ - -// state object// -var setVertexAttribArrays = require( './setVertexAttribArrays' ); - -/** - * Helper class to work with WebGL VertexArrayObjects (vaos) - * Only works if WebGL extensions are enabled (they usually are) - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - */ -function VertexArrayObject(gl, state) -{ - - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); - - this.nativeState = state; - - if(this.nativeVaoExtension) - { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - - var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - - // VAO - overwrite the state.. - this.nativeState = { - tempAttribState: new Array(maxAttribs), - attribState: new Array(maxAttribs) - }; - } - - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * An array of attributes ? @mat - * - * @member {Array} - */ - this.attributes = []; - - /** - * @mat - * - * @member {Array} - */ - this.indexBuffer = null; - - /** - * A boolean flag - * - * @member {Boolean} - */ - this.dirty = false; -} - -VertexArrayObject.prototype.constructor = VertexArrayObject; -module.exports = VertexArrayObject; - - -/** - * Binds the buffer - */ -VertexArrayObject.prototype.bind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - - if(this.dirty) - { - this.dirty = false; - this.activate(); - } - } - else - { - - this.activate(); - } - - return this; -}; - -/** - * Unbinds the buffer - */ -VertexArrayObject.prototype.unbind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(null); - } - - return this; -}; - -/** - * Uses this vao - */ -VertexArrayObject.prototype.activate = function() -{ - - var gl = this.gl; - var lastBuffer = null; - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - - if(lastBuffer !== attrib.buffer) - { - attrib.buffer.bind(); - lastBuffer = attrib.buffer; - } - - //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.start || 0); - - - } - - setVertexAttribArrays(gl, this.attributes, this.nativeState); - - this.indexBuffer.bind(); - - return this; -}; - -/** - * - * @param buffer {WebGLBuffer} - * @param attribute {[type]} - * @param type {[type]} - * @param normalized {[type]} - * @param stride {Number} - * @param start {Number} - */ -VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) -{ - this.attributes.push({ - buffer: buffer, - attribute: attribute, - - location: attribute.location, - type: type || this.gl.FLOAT, - normalized: normalized || false, - stride: stride || 0, - start: start || 0 - }); - - this.dirty = true; - - return this; -}; - -/** - * - * @param buffer {WebGLBuffer} - * @param options {Object} - */ -VertexArrayObject.prototype.addIndex = function(buffer, options) -{ - this.indexBuffer = buffer; - - this.dirty = true; - - return this; -}; - -/** - * Unbinds this vao and disables it - */ -VertexArrayObject.prototype.clear = function() -{ - var gl = this.gl; - - // TODO - should this function unbind after clear? - // for now, no but lets see what happens in the real world! - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - } - - this.attributes.length = 0; - this.indexBuffer = null; - - return this; -}; - -/** - * @mat - * @param type {Number} - * @param size {Number} - * @param start {Number} - */ -VertexArrayObject.prototype.draw = function(type, size, start) -{ - var gl = this.gl; - gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); - - return this; -}; - -/** - * Destroy this vao - */ -VertexArrayObject.prototype.destroy = function() -{ - // lose references - this.gl = null; - this.indexBuffer = null; - this.attributes = null; - this.nativeState = null; - - if(this.nativeVao) - { - this.nativeVaoExtension.deleteVertexArrayOES(this.nativeVao); - } - - this.nativeVaoExtension = null; - this.nativeVao = null; -}; - -},{"./setVertexAttribArrays":8}],7:[function(require,module,exports){ - -/** - * Helper class to create a webGL Context - * - * @class - * @memberof pixi.gl - * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from - * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, - * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available - * @return {WebGLRenderingContext} the WebGL context - */ -var createContext = function(canvas, options) -{ - var gl = canvas.getContext('webgl', options) || - canvas.getContext('experimental-webgl', options); - - if (!gl) - { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - return gl; -}; - -module.exports = createContext; - -},{}],8:[function(require,module,exports){ -var GL_MAP = {}; - -/** - * @mat - * @param gl {WebGLRenderingContext} The current WebGL context - * @param attribs {[type]} - */ -var setVertexAttribArrays = function (gl, attribs, state) -{ - var i; - if(state) - { - var tempAttribState = state.tempAttribState, - attribState = state.attribState; - - for (i = 0; i < tempAttribState.length; i++) - { - tempAttribState[i] = false; - } - - // set the new attribs - for (i = 0; i < attribs.length; i++) - { - tempAttribState[attribs[i].attribute.location] = true; - } - - for (i = 0; i < attribState.length; i++) - { - if (attribState[i] !== tempAttribState[i]) - { - attribState[i] = tempAttribState[i]; - - if (state.attribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } - } - } - - } - else - { - for (i = 0; i < attribs.length; i++) - { - var attrib = attribs[i]; - gl.enableVertexAttribArray(attrib.attribute.location); - } - } -}; - -module.exports = setVertexAttribArrays; - -},{}],9:[function(require,module,exports){ - -/** - * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @return {WebGLProgram} the shader program - */ -var compileProgram = function(gl, vertexSrc, fragmentSrc) -{ - var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); - var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); - - var program = gl.createProgram(); - - gl.attachShader(program, glVertShader); - gl.attachShader(program, glFragShader); - gl.linkProgram(program); - - // if linking fails, then log and cleanup - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) - { - console.error('Pixi.js Error: Could not initialize shader.'); - console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); - console.error('gl.getError()', gl.getError()); - - // if there is a program info log, log it - if (gl.getProgramInfoLog(program) !== '') - { - console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); - } - - gl.deleteProgram(program); - program = null; - } - - // clean up some shaders - gl.deleteShader(glVertShader); - gl.deleteShader(glFragShader); - - return program; -}; - -/** - * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @return {WebGLShader} the shader - */ -var compileShader = function (gl, type, src) -{ - var shader = gl.createShader(type); - - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) - { - console.log(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -}; - -module.exports = compileProgram; - -},{}],10:[function(require,module,exports){ - - -var defaultValue = function(type, size) -{ - switch (type) - { - case 'float': - return 0; - - case 'vec2': - return new Float32Array(2 * size); - - case 'vec3': - return new Float32Array(3 * size); - - case 'vec4': - return new Float32Array(4 * size); - - case 'int': - case 'sampler2D': - return 0; - - case 'ivec2': - return new Int32Array(2 * size); - - case 'ivec3': - return new Int32Array(3 * size); - - case 'ivec4': - return new Int32Array(4 * size); - - case 'bool': - return false; - - case 'bvec2': - - return booleanArray( 2 * size); - - case 'bvec3': - return booleanArray(3 * size); - - case 'bvec4': - return booleanArray(4 * size); - - case 'mat2': - return new Float32Array([1, 0, - 0, 1]); - - case 'mat3': - return new Float32Array([1, 0, 0, - 0, 1, 0, - 0, 0, 1]); - - case 'mat4': - return new Float32Array([1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]); - } -}; - -var booleanArray = function(size) -{ - var array = new Array(size); - - for (var i = 0; i < array.length; i++) - { - array[i] = false; - } - - return array; -}; - -module.exports = defaultValue; - -},{}],11:[function(require,module,exports){ - -var mapType = require('./mapType'); -var mapSize = require('./mapSize'); - -/** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} - */ -var extractAttributes = function(gl, program) -{ - var attributes = {}; - - var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - - for (var i = 0; i < totalAttributes; i++) - { - var attribData = gl.getActiveAttrib(program, i); - var type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type:type, - size:mapSize(type), - location:gl.getAttribLocation(program, attribData.name), - //TODO - make an attribute object - pointer: pointer - }; - } - - return attributes; -}; - -var pointer = function(type, normalized, stride, start){ - // console.log(this.location) - gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); -}; - -module.exports = extractAttributes; - -},{"./mapSize":14,"./mapType":15}],12:[function(require,module,exports){ -var mapType = require('./mapType'); -var defaultValue = require('./defaultValue'); - -/** - * Extracts the uniforms - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -var extractUniforms = function(gl, program) -{ - var uniforms = {}; - - var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - - for (var i = 0; i < totalUniforms; i++) - { - var uniformData = gl.getActiveUniform(program, i); - var name = uniformData.name.replace(/\[.*?\]/, ""); - var type = mapType(gl, uniformData.type ); - - uniforms[name] = { - type:type, - size:uniformData.size, - location:gl.getUniformLocation(program, name), - value:defaultValue(type, uniformData.size) - }; - } - - return uniforms; -}; - -module.exports = extractUniforms; - -},{"./defaultValue":10,"./mapType":15}],13:[function(require,module,exports){ -/** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param uniforms {Array} @mat ? - * @return attributes {Object} - */ -var generateUniformAccessObject = function(gl, uniformData) -{ - // this is the object we will be sending back. - // an object hierachy will be created for structs - var uniforms = {data:{}}; - - uniforms.gl = gl; - - var uniformKeys= Object.keys(uniformData); - - for (var i = 0; i < uniformKeys.length; i++) - { - var fullName = uniformKeys[i]; - - var nameTokens = fullName.split('.'); - var name = nameTokens[nameTokens.length - 1]; - - var uniformGroup = getUniformGroup(nameTokens, uniforms); - - var uniform = uniformData[fullName]; - uniformGroup.data[name] = uniform; - - uniformGroup.gl = gl; - - Object.defineProperty(uniformGroup, name, { - get: generateGetter(name), - set: generateSetter(name, uniform) - }); - } - - return uniforms; -}; - -var generateGetter = function(name) -{ - var template = getterTemplate.replace('%%', name); - return new Function(template); // jshint ignore:line -}; - -var generateSetter = function(name, uniform) -{ - var template = setterTemplate.replace(/%%/g, name); - var setTemplate; - - if(uniform.size === 1) - { - setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; - } - else - { - setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; - } - - if(setTemplate) - { - template += "\nthis.gl." + setTemplate + ";"; - } - - return new Function('value', template); // jshint ignore:line -}; - -var getUniformGroup = function(nameTokens, uniform) -{ - var cur = uniform; - - for (var i = 0; i < nameTokens.length - 1; i++) - { - var o = cur[nameTokens[i]] || {data:{}}; - cur[nameTokens[i]] = o; - cur = o; - } - - return cur; -}; - -var getterTemplate = [ - 'return this.data.%%.value;', -].join('\n'); - -var setterTemplate = [ - 'this.data.%%.value = value;', - 'var location = this.data.%%.location;' -].join('\n'); - - -var GLSL_TO_SINGLE_SETTERS = { - - 'float': 'uniform1f(location, value)', - - 'vec2': 'uniform2f(location, value[0], value[1])', - 'vec3': 'uniform3f(location, value[0], value[1], value[2])', - 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', - - 'int': 'uniform1i(location, value)', - 'ivec2': 'uniform2i(location, value[0], value[1])', - 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', - 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'bool': 'uniform1i(location, value)', - 'bvec2': 'uniform2i(location, value[0], value[1])', - 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', - 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'mat2': 'uniformMatrix2fv(location, false, value)', - 'mat3': 'uniformMatrix3fv(location, false, value)', - 'mat4': 'uniformMatrix4fv(location, false, value)', - - 'sampler2D':'uniform1i(location, value)' -}; - -var GLSL_TO_ARRAY_SETTERS = { - - 'float': 'uniform1fv(location, value)', - - 'vec2': 'uniform2fv(location, value)', - 'vec3': 'uniform3fv(location, value)', - 'vec4': 'uniform4fv(location, value)', - - 'int': 'uniform1iv(location, value)', - 'ivec2': 'uniform2iv(location, value)', - 'ivec3': 'uniform3iv(location, value)', - 'ivec4': 'uniform4iv(location, value)', - - 'bool': 'uniform1iv(location, value)', - 'bvec2': 'uniform2iv(location, value)', - 'bvec3': 'uniform3iv(location, value)', - 'bvec4': 'uniform4iv(location, value)', - - 'sampler2D':'uniform1iv(location, value)' -}; - -module.exports = generateUniformAccessObject; - -},{}],14:[function(require,module,exports){ - - -var mapSize = function(type) -{ - return GLSL_TO_SIZE[type]; -}; - - -var GLSL_TO_SIZE = { - 'float': 1, - 'vec2': 2, - 'vec3': 3, - 'vec4': 4, - - 'int': 1, - 'ivec2': 2, - 'ivec3': 3, - 'ivec4': 4, - - 'bool': 1, - 'bvec2': 2, - 'bvec3': 3, - 'bvec4': 4, - - 'mat2': 4, - 'mat3': 9, - 'mat4': 16, - - 'sampler2D': 1 -}; - -module.exports = mapSize; - -},{}],15:[function(require,module,exports){ - - -var mapSize = function(gl, type) -{ - if(!GL_TABLE) - { - var typeNames = Object.keys(GL_TO_GLSL_TYPES); - - GL_TABLE = {}; - - for(var i = 0; i < typeNames.length; ++i) - { - var tn = typeNames[i]; - GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; - } - } - - return GL_TABLE[type]; -}; - -var GL_TABLE = null; - -var GL_TO_GLSL_TYPES = { - 'FLOAT': 'float', - 'FLOAT_VEC2': 'vec2', - 'FLOAT_VEC3': 'vec3', - 'FLOAT_VEC4': 'vec4', - - 'INT': 'int', - 'INT_VEC2': 'ivec2', - 'INT_VEC3': 'ivec3', - 'INT_VEC4': 'ivec4', - - 'BOOL': 'bool', - 'BOOL_VEC2': 'bvec2', - 'BOOL_VEC3': 'bvec3', - 'BOOL_VEC4': 'bvec4', - - 'FLOAT_MAT2': 'mat2', - 'FLOAT_MAT3': 'mat3', - 'FLOAT_MAT4': 'mat4', - - 'SAMPLER_2D': 'sampler2D' -}; - -module.exports = mapSize; - -},{}],16:[function(require,module,exports){ (function (process,global){ /*! * async @@ -2795,7 +1267,7 @@ }()); }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":19}],17:[function(require,module,exports){ +},{"_process":4}],2:[function(require,module,exports){ /** * Bit twiddling hacks for JavaScript. * @@ -3001,7 +1473,7 @@ } -},{}],18:[function(require,module,exports){ +},{}],3:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -3229,7 +1701,7 @@ ; }).call(this,require('_process')) -},{"_process":19}],19:[function(require,module,exports){ +},{"_process":4}],4:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -3322,7 +1794,7 @@ }; process.umask = function() { return 0; }; -},{}],20:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ (function (global){ /*! https://mths.be/punycode v1.4.0 by @mathias */ ;(function(root) { @@ -3859,7 +2331,7 @@ }(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],21:[function(require,module,exports){ +},{}],6:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -3945,7 +2417,7 @@ return Object.prototype.toString.call(xs) === '[object Array]'; }; -},{}],22:[function(require,module,exports){ +},{}],7:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -4032,13 +2504,13 @@ return res; }; -},{}],23:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ 'use strict'; exports.decode = exports.parse = require('./decode'); exports.encode = exports.stringify = require('./encode'); -},{"./decode":21,"./encode":22}],24:[function(require,module,exports){ +},{"./decode":6,"./encode":7}],9:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -4747,7 +3219,7 @@ return arg == null; } -},{"punycode":20,"querystring":23}],25:[function(require,module,exports){ +},{"punycode":5,"querystring":8}],10:[function(require,module,exports){ 'use strict'; module.exports = earcut; @@ -5393,7 +3865,7 @@ return result; }; -},{}],26:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ 'use strict'; var has = Object.prototype.hasOwnProperty; @@ -5684,7 +4156,7 @@ module.exports = EventEmitter; } -},{}],27:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ /** * isMobile.js v0.4.0 * @@ -5823,9 +4295,9 @@ })(this); -},{}],28:[function(require,module,exports){ -/* eslint-disable no-unused-vars */ +},{}],13:[function(require,module,exports){ 'use strict'; +/* eslint-disable no-unused-vars */ var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; @@ -5837,7 +4309,51 @@ return Object(val); } -module.exports = Object.assign || function (target, source) { +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } + + return true; + } catch (e) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} + +module.exports = shouldUseNative() ? Object.assign : function (target, source) { var from; var to = toObject(target); var symbols; @@ -5864,6 +4380,1534 @@ return to; }; +},{}],14:[function(require,module,exports){ + + +module.exports = { + + createContext: require('./lib/createContext'), + setVertexAttribArrays: require('./lib/setVertexAttribArrays'), + + GLBuffer: require('./lib/GLBuffer'), + GLFramebuffer: require('./lib/GLFramebuffer'), + GLShader: require('./lib/GLShader'), + GLTexture: require('./lib/GLTexture'), + + VertexArrayObject: require('./lib/VertexArrayObject') + +}; +},{"./lib/GLBuffer":15,"./lib/GLFramebuffer":16,"./lib/GLShader":17,"./lib/GLTexture":18,"./lib/VertexArrayObject":19,"./lib/createContext":20,"./lib/setVertexAttribArrays":21}],15:[function(require,module,exports){ +var EMPTY_ARRAY_BUFFER = new ArrayBuffer(0); + +/** + * Helper class to create a webGL buffer + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param type {gl.ARRAY_BUFFER | gl.ELEMENT_ARRAY_BUFFER} @mat + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + * @param drawType {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + */ +var Buffer = function(gl, type, data, drawType) +{ + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The WebGL buffer, created upon instantiation + * + * @member {WebGLBuffer} + */ + this.buffer = gl.createBuffer(); + + /** + * The type of the buffer + * + * @member {gl.ARRAY_BUFFER || gl.ELEMENT_ARRAY_BUFFER} + */ + this.type = type || gl.ARRAY_BUFFER; + + /** + * The draw type of the buffer + * + * @member {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + */ + this.drawType = drawType || gl.STATIC_DRAW; + + /** + * The data in the buffer, as a typed array + * + * @member {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} + */ + this.data = EMPTY_ARRAY_BUFFER; + + if(data) + { + this.upload(data); + } +}; + +/** + * Uploads the buffer to the GPU + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data to upload + * @param offset {Number} if only a subset of the data should be uploaded, this is the amount of data to subtract + * @param dontBind {Boolean} whether to bind the buffer before uploading it + */ +Buffer.prototype.upload = function(data, offset, dontBind) +{ + // todo - needed? + if(!dontBind) this.bind(); + + var gl = this.gl; + + data = data || this.data; + offset = offset || 0; + + if(this.data.byteLength >= data.byteLength) + { + gl.bufferSubData(this.type, offset, data); + } + else + { + gl.bufferData(this.type, data, this.drawType); + } + + this.data = data; +}; +/** + * Binds the buffer + * + */ +Buffer.prototype.bind = function() +{ + var gl = this.gl; + gl.bindBuffer(this.type, this.buffer); +}; + +Buffer.createVertexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); +}; + +Buffer.createIndexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); +}; + +Buffer.create = function(gl, type, data, drawType) +{ + return new Buffer(gl, type, drawType); +}; + +/** + * Destroys the buffer + * + */ +Buffer.prototype.destroy = function(){ + this.gl.deleteBuffer(this.buffer); +}; + +module.exports = Buffer; + +},{}],16:[function(require,module,exports){ + +var Texture = require('./GLTexture'); + +/** + * Helper class to create a webGL Framebuffer + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + */ +var Framebuffer = function(gl, width, height) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The frame buffer + * + * @member {WebGLFramebuffer} + */ + this.framebuffer = gl.createFramebuffer(); + + /** + * The stencil buffer + * + * @member {WebGLRenderbuffer} + */ + this.stencil = null; + + /** + * The stencil buffer + * + * @member {GLTexture} + */ + this.texture = null; + + /** + * The width of the drawing area of the buffer + * + * @member {Number} + */ + this.width = width || 100; + /** + * The height of the drawing area of the buffer + * + * @member {Number} + */ + this.height = height || 100; +}; + +/** + * Adds a texture to the frame buffer + * @param texture {GLTexture} + */ +Framebuffer.prototype.enableTexture = function(texture) +{ + var gl = this.gl; + + this.texture = texture || new Texture(gl); + + this.texture.bind(); + + //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + this.bind(); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); +}; + +/** + * Initialises the stencil buffer + * @mat maybe you can come up with a better explaination + */ +Framebuffer.prototype.enableStencil = function() +{ + if(this.stencil)return; + + var gl = this.gl; + + this.stencil = gl.createRenderbuffer(); + + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + + // TODO.. this is depth AND stencil? + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); +}; + +/** + * Erases the drawing area and fills it with a colour + * @param r {Number} the red value of the clearing colour + * @param g {Number} the green value of the clearing colour + * @param b {Number} the blue value of the clearing colour + * @param a {Number} the alpha value of the clearing colour + */ +Framebuffer.prototype.clear = function( r, g, b, a ) +{ + this.bind(); + + var gl = this.gl; + + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT); +}; + +/** + * Binds the frame buffer to the WebGL context + */ +Framebuffer.prototype.bind = function() +{ + var gl = this.gl; + + if(this.texture) + { + this.texture.unbind(); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); +}; + +/** + * Unbinds the frame buffer to the WebGL context + */ +Framebuffer.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, null ); +}; +/** + * Resizes the drawing area of the buffer to the given width and height + * @param width {Number} the new width + * @param height {Number} the new height + */ +Framebuffer.prototype.resize = function(width, height) +{ + var gl = this.gl; + + this.width = width; + this.height = height; + + if ( this.texture ) + { + this.texture.uploadData(null, width, height); + } + + if ( this.stencil ) + { + // update the stencil buffer width and height + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + } +}; + +/** + * Destroys this buffer + */ +Framebuffer.prototype.destroy = function() +{ + var gl = this.gl; + + //TODO + if(this.texture) + { + this.texture.destroy(); + } + + gl.deleteFramebuffer(this.framebuffer); + + this.gl = null; + + this.stencil = null; + this.texture = null; +}; + +/** + * Creates a frame buffer with a texture containing the given data + * @mat can you confirm ? :) + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createRGBA = function(gl, width, height, data) +{ + var texture = Texture.fromData(gl, null, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture); + + fbo.unbind(); + + return fbo; +}; + +/** + * Creates a frame buffer with a texture containing the given data + * @mat not sure what the difference is with the method above ? + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createFloat32 = function(gl, width, height, data) +{ + // create a new texture.. + var texture = new Texture.fromData(gl, data, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture); + + fbo.unbind(); + + return fbo; +}; + +module.exports = Framebuffer; + +},{"./GLTexture":18}],17:[function(require,module,exports){ + +var compileProgram = require('./shader/compileProgram'), + extractAttributes = require('./shader/extractAttributes'), + extractUniforms = require('./shader/extractUniforms'), + generateUniformAccessObject = require('./shader/generateUniformAccessObject'); + +/** + * Helper class to create a webGL Shader + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + */ +var Shader = function(gl, vertexSrc, fragmentSrc) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The shader program + * + * @member {WebGLProgram} + */ + // First compile the program.. + this.program = compileProgram(gl, vertexSrc, fragmentSrc); + + + /** + * The attributes of the shader as an object containing the following properties + * { + * type, + * size, + * location, + * pointer + * } + * @member {Object} + */ + // next extract the attributes + this.attributes = extractAttributes(gl, this.program); + + var uniformData = extractUniforms(gl, this.program); + + /** + * The uniforms of the shader as an object containing the following properties + * { + * gl, + * data + * } + * @member {Object} + */ + this.uniforms = generateUniformAccessObject( gl, uniformData ); +}; +/** + * Uses this shader + */ +Shader.prototype.bind = function() +{ + this.gl.useProgram(this.program); +}; + +/** + * Destroys this shader + * TODO + */ +Shader.prototype.destroy = function() +{ + var gl = this.gl; +}; + +module.exports = Shader; + +},{"./shader/compileProgram":22,"./shader/extractAttributes":24,"./shader/extractUniforms":25,"./shader/generateUniformAccessObject":26}],18:[function(require,module,exports){ + +/** + * Helper class to create a WebGL Texture + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL context + * @param width {number} the width of the texture + * @param height {number} the height of the texture + * @param format {number} the pixel format of the texture. defaults to gl.RGBA + * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE + */ +var Texture = function(gl, width, height, format, type) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + + /** + * The WebGL texture + * + * @member {WebGLTexture} + */ + this.texture = gl.createTexture(); + + /** + * If mipmapping was used for this texture, enable and disable with enableMipmap() + * + * @member {Boolean} + */ + // some settings.. + this.mipmap = false; + + + /** + * Set to true to enable pre-multiplied alpha + * + * @member {Boolean} + */ + this.premultiplyAlpha = false; + + /** + * The width of texture + * + * @member {Number} + */ + this.width = width || 0; + /** + * The height of texture + * + * @member {Number} + */ + this.height = height || 0; + + /** + * The pixel format of the texture. defaults to gl.RGBA + * + * @member {Number} + */ + this.format = format || gl.RGBA; + + /** + * The gl type of the texture. defaults to gl.UNSIGNED_BYTE + * + * @member {Number} + */ + this.type = type || gl.UNSIGNED_BYTE; + + +}; + +/** + * Uploads this texture to the GPU + * @param source {HTMLImageElement|ImageData|HTMLVideoElement} the source image of the texture + */ +Texture.prototype.upload = function(source) +{ + this.bind(); + + var gl = this.gl; + + // if the source is a video, we need to use the videoWidth / videoHeight properties as width / height will be incorrect. + this.width = source.videoWidth || source.width; + this.height = source.videoHeight || source.height; + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); +}; + +var FLOATING_POINT_AVAILABLE = false; + +/** + * Use a data source and uploads this texture to the GPU + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.prototype.uploadData = function(data, width, height) +{ + this.bind(); + + var gl = this.gl; + + this.width = width || this.width; + this.height = height || this.height; + + if(data instanceof Float32Array) + { + if(!FLOATING_POINT_AVAILABLE) + { + var ext = gl.getExtension("OES_texture_float"); + + if(ext) + { + FLOATING_POINT_AVAILABLE = true; + } + else + { + throw new Error('floating point textures not available'); + } + } + + this.type = gl.FLOAT; + } + else + { + // TODO support for other types + this.type = gl.UNSIGNED_BYTE; + } + + + + // what type of data? + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); + +}; + +/** + * Binds the texture + * @param location {@mat} + */ +Texture.prototype.bind = function(location) +{ + var gl = this.gl; + + if(location !== undefined) + { + gl.activeTexture(gl.TEXTURE0 + location); + } + + gl.bindTexture(gl.TEXTURE_2D, this.texture); +}; + +/** + * Unbinds the texture + */ +Texture.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindTexture(gl.TEXTURE_2D, null); +}; + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.minFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + if(this.mipmap) + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); + } + else + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); + } +}; + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.magFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); +}; + +/** + * Enables mipmapping + */ +Texture.prototype.enableMipmap = function() +{ + var gl = this.gl; + + this.bind(); + + this.mipmap = true; + + gl.generateMipmap(gl.TEXTURE_2D); +}; + +/** + * Enables linear filtering + */ +Texture.prototype.enableLinearScaling = function() +{ + this.minFilter(true); + this.magFilter(true); +}; + +/** + * Enables nearest neighbour interpolation + */ +Texture.prototype.enableNearestScaling = function() +{ + this.minFilter(false); + this.magFilter(false); +}; + +/** + * Enables clamping on the texture so WebGL will not repeat it + */ +Texture.prototype.enableWrapClamp = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); +}; + +/** + * Enable tiling on the texture + */ +Texture.prototype.enableWrapRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); +}; + +/** + * @mat + */ +Texture.prototype.enableWrapMirrorRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); +}; + + +/** + * Destroys this texture + */ +Texture.prototype.destroy = function() +{ + var gl = this.gl; + //TODO + gl.deleteTexture(this.texture); +}; + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param source {HTMLImageElement|ImageData} the source image of the texture + * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha + */ +Texture.fromSource = function(gl, source, premultiplyAlpha) +{ + var texture = new Texture(gl); + texture.premultiplyAlpha = premultiplyAlpha || false; + texture.upload(source); + + return texture; +}; + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.fromData = function(gl, data, width, height) +{ + //console.log(data, width, height); + var texture = new Texture(gl); + texture.uploadData(data, width, height); + + return texture; +}; + + +module.exports = Texture; + +},{}],19:[function(require,module,exports){ + +// state object// +var setVertexAttribArrays = require( './setVertexAttribArrays' ); + +/** + * Helper class to work with WebGL VertexArrayObjects (vaos) + * Only works if WebGL extensions are enabled (they usually are) + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + */ +function VertexArrayObject(gl, state) +{ + + this.nativeVaoExtension = ( + gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object') + ); + + this.nativeState = state; + + if(this.nativeVaoExtension) + { + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + + // VAO - overwrite the state.. + this.nativeState = { + tempAttribState: new Array(maxAttribs), + attribState: new Array(maxAttribs) + }; + } + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * An array of attributes ? @mat + * + * @member {Array} + */ + this.attributes = []; + + /** + * @mat + * + * @member {Array} + */ + this.indexBuffer = null; + + /** + * A boolean flag + * + * @member {Boolean} + */ + this.dirty = false; +} + +VertexArrayObject.prototype.constructor = VertexArrayObject; +module.exports = VertexArrayObject; + + +/** + * Binds the buffer + */ +VertexArrayObject.prototype.bind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + + if(this.dirty) + { + this.dirty = false; + this.activate(); + } + } + else + { + + this.activate(); + } + + return this; +}; + +/** + * Unbinds the buffer + */ +VertexArrayObject.prototype.unbind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + return this; +}; + +/** + * Uses this vao + */ +VertexArrayObject.prototype.activate = function() +{ + + var gl = this.gl; + var lastBuffer = null; + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + + if(lastBuffer !== attrib.buffer) + { + attrib.buffer.bind(); + lastBuffer = attrib.buffer; + } + + //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.start || 0); + + + } + + setVertexAttribArrays(gl, this.attributes, this.nativeState); + + this.indexBuffer.bind(); + + return this; +}; + +/** + * + * @param buffer {WebGLBuffer} + * @param attribute {[type]} + * @param type {[type]} + * @param normalized {[type]} + * @param stride {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) +{ + this.attributes.push({ + buffer: buffer, + attribute: attribute, + + location: attribute.location, + type: type || this.gl.FLOAT, + normalized: normalized || false, + stride: stride || 0, + start: start || 0 + }); + + this.dirty = true; + + return this; +}; + +/** + * + * @param buffer {WebGLBuffer} + * @param options {Object} + */ +VertexArrayObject.prototype.addIndex = function(buffer, options) +{ + this.indexBuffer = buffer; + + this.dirty = true; + + return this; +}; + +/** + * Unbinds this vao and disables it + */ +VertexArrayObject.prototype.clear = function() +{ + var gl = this.gl; + + // TODO - should this function unbind after clear? + // for now, no but lets see what happens in the real world! + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + } + + this.attributes.length = 0; + this.indexBuffer = null; + + return this; +}; + +/** + * @mat + * @param type {Number} + * @param size {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.draw = function(type, size, start) +{ + var gl = this.gl; + gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); + + return this; +}; + +/** + * Destroy this vao + */ +VertexArrayObject.prototype.destroy = function() +{ + // lose references + this.gl = null; + this.indexBuffer = null; + this.attributes = null; + this.nativeState = null; + + if(this.nativeVao) + { + this.nativeVaoExtension.deleteVertexArrayOES(this.nativeVao); + } + + this.nativeVaoExtension = null; + this.nativeVao = null; +}; + +},{"./setVertexAttribArrays":21}],20:[function(require,module,exports){ + +/** + * Helper class to create a webGL Context + * + * @class + * @memberof pixi.gl + * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from + * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, + * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available + * @return {WebGLRenderingContext} the WebGL context + */ +var createContext = function(canvas, options) +{ + var gl = canvas.getContext('webgl', options) || + canvas.getContext('experimental-webgl', options); + + if (!gl) + { + // fail, not able to get a context + throw new Error('This browser does not support webGL. Try using the canvas renderer'); + } + + return gl; +}; + +module.exports = createContext; + +},{}],21:[function(require,module,exports){ +var GL_MAP = {}; + +/** + * @mat + * @param gl {WebGLRenderingContext} The current WebGL context + * @param attribs {[type]} + */ +var setVertexAttribArrays = function (gl, attribs, state) +{ + var i; + if(state) + { + var tempAttribState = state.tempAttribState, + attribState = state.attribState; + + for (i = 0; i < tempAttribState.length; i++) + { + tempAttribState[i] = false; + } + + // set the new attribs + for (i = 0; i < attribs.length; i++) + { + tempAttribState[attribs[i].attribute.location] = true; + } + + for (i = 0; i < attribState.length; i++) + { + if (attribState[i] !== tempAttribState[i]) + { + attribState[i] = tempAttribState[i]; + + if (state.attribState[i]) + { + gl.enableVertexAttribArray(i); + } + else + { + gl.disableVertexAttribArray(i); + } + } + } + + } + else + { + for (i = 0; i < attribs.length; i++) + { + var attrib = attribs[i]; + gl.enableVertexAttribArray(attrib.attribute.location); + } + } +}; + +module.exports = setVertexAttribArrays; + +},{}],22:[function(require,module,exports){ + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + * @return {WebGLProgram} the shader program + */ +var compileProgram = function(gl, vertexSrc, fragmentSrc) +{ + var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); + var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); + + var program = gl.createProgram(); + + gl.attachShader(program, glVertShader); + gl.attachShader(program, glFragShader); + gl.linkProgram(program); + + // if linking fails, then log and cleanup + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) + { + console.error('Pixi.js Error: Could not initialize shader.'); + console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); + console.error('gl.getError()', gl.getError()); + + // if there is a program info log, log it + if (gl.getProgramInfoLog(program) !== '') + { + console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); + } + + gl.deleteProgram(program); + program = null; + } + + // clean up some shaders + gl.deleteShader(glVertShader); + gl.deleteShader(glFragShader); + + return program; +}; + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @return {WebGLShader} the shader + */ +var compileShader = function (gl, type, src) +{ + var shader = gl.createShader(type); + + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) + { + console.log(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +}; + +module.exports = compileProgram; + +},{}],23:[function(require,module,exports){ + + +var defaultValue = function(type, size) +{ + switch (type) + { + case 'float': + return 0; + + case 'vec2': + return new Float32Array(2 * size); + + case 'vec3': + return new Float32Array(3 * size); + + case 'vec4': + return new Float32Array(4 * size); + + case 'int': + case 'sampler2D': + return 0; + + case 'ivec2': + return new Int32Array(2 * size); + + case 'ivec3': + return new Int32Array(3 * size); + + case 'ivec4': + return new Int32Array(4 * size); + + case 'bool': + return false; + + case 'bvec2': + + return booleanArray( 2 * size); + + case 'bvec3': + return booleanArray(3 * size); + + case 'bvec4': + return booleanArray(4 * size); + + case 'mat2': + return new Float32Array([1, 0, + 0, 1]); + + case 'mat3': + return new Float32Array([1, 0, 0, + 0, 1, 0, + 0, 0, 1]); + + case 'mat4': + return new Float32Array([1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]); + } +}; + +var booleanArray = function(size) +{ + var array = new Array(size); + + for (var i = 0; i < array.length; i++) + { + array[i] = false; + } + + return array; +}; + +module.exports = defaultValue; + +},{}],24:[function(require,module,exports){ + +var mapType = require('./mapType'); +var mapSize = require('./mapSize'); + +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the attributes from + * @return attributes {Object} + */ +var extractAttributes = function(gl, program) +{ + var attributes = {}; + + var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); + + for (var i = 0; i < totalAttributes; i++) + { + var attribData = gl.getActiveAttrib(program, i); + var type = mapType(gl, attribData.type); + + attributes[attribData.name] = { + type:type, + size:mapSize(type), + location:gl.getAttribLocation(program, attribData.name), + //TODO - make an attribute object + pointer: pointer + }; + } + + return attributes; +}; + +var pointer = function(type, normalized, stride, start){ + // console.log(this.location) + gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); +}; + +module.exports = extractAttributes; + +},{"./mapSize":27,"./mapType":28}],25:[function(require,module,exports){ +var mapType = require('./mapType'); +var defaultValue = require('./defaultValue'); + +/** + * Extracts the uniforms + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the uniforms from + * @return uniforms {Object} + */ +var extractUniforms = function(gl, program) +{ + var uniforms = {}; + + var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + + for (var i = 0; i < totalUniforms; i++) + { + var uniformData = gl.getActiveUniform(program, i); + var name = uniformData.name.replace(/\[.*?\]/, ""); + var type = mapType(gl, uniformData.type ); + + uniforms[name] = { + type:type, + size:uniformData.size, + location:gl.getUniformLocation(program, name), + value:defaultValue(type, uniformData.size) + }; + } + + return uniforms; +}; + +module.exports = extractUniforms; + +},{"./defaultValue":23,"./mapType":28}],26:[function(require,module,exports){ +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param uniforms {Array} @mat ? + * @return attributes {Object} + */ +var generateUniformAccessObject = function(gl, uniformData) +{ + // this is the object we will be sending back. + // an object hierachy will be created for structs + var uniforms = {data:{}}; + + uniforms.gl = gl; + + var uniformKeys= Object.keys(uniformData); + + for (var i = 0; i < uniformKeys.length; i++) + { + var fullName = uniformKeys[i]; + + var nameTokens = fullName.split('.'); + var name = nameTokens[nameTokens.length - 1]; + + var uniformGroup = getUniformGroup(nameTokens, uniforms); + + var uniform = uniformData[fullName]; + uniformGroup.data[name] = uniform; + + uniformGroup.gl = gl; + + Object.defineProperty(uniformGroup, name, { + get: generateGetter(name), + set: generateSetter(name, uniform) + }); + } + + return uniforms; +}; + +var generateGetter = function(name) +{ + var template = getterTemplate.replace('%%', name); + return new Function(template); // jshint ignore:line +}; + +var generateSetter = function(name, uniform) +{ + var template = setterTemplate.replace(/%%/g, name); + var setTemplate; + + if(uniform.size === 1) + { + setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; + } + else + { + setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; + } + + if(setTemplate) + { + template += "\nthis.gl." + setTemplate + ";"; + } + + return new Function('value', template); // jshint ignore:line +}; + +var getUniformGroup = function(nameTokens, uniform) +{ + var cur = uniform; + + for (var i = 0; i < nameTokens.length - 1; i++) + { + var o = cur[nameTokens[i]] || {data:{}}; + cur[nameTokens[i]] = o; + cur = o; + } + + return cur; +}; + +var getterTemplate = [ + 'return this.data.%%.value;', +].join('\n'); + +var setterTemplate = [ + 'this.data.%%.value = value;', + 'var location = this.data.%%.location;' +].join('\n'); + + +var GLSL_TO_SINGLE_SETTERS = { + + 'float': 'uniform1f(location, value)', + + 'vec2': 'uniform2f(location, value[0], value[1])', + 'vec3': 'uniform3f(location, value[0], value[1], value[2])', + 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', + + 'int': 'uniform1i(location, value)', + 'ivec2': 'uniform2i(location, value[0], value[1])', + 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', + 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'bool': 'uniform1i(location, value)', + 'bvec2': 'uniform2i(location, value[0], value[1])', + 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', + 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'mat2': 'uniformMatrix2fv(location, false, value)', + 'mat3': 'uniformMatrix3fv(location, false, value)', + 'mat4': 'uniformMatrix4fv(location, false, value)', + + 'sampler2D':'uniform1i(location, value)' +}; + +var GLSL_TO_ARRAY_SETTERS = { + + 'float': 'uniform1fv(location, value)', + + 'vec2': 'uniform2fv(location, value)', + 'vec3': 'uniform3fv(location, value)', + 'vec4': 'uniform4fv(location, value)', + + 'int': 'uniform1iv(location, value)', + 'ivec2': 'uniform2iv(location, value)', + 'ivec3': 'uniform3iv(location, value)', + 'ivec4': 'uniform4iv(location, value)', + + 'bool': 'uniform1iv(location, value)', + 'bvec2': 'uniform2iv(location, value)', + 'bvec3': 'uniform3iv(location, value)', + 'bvec4': 'uniform4iv(location, value)', + + 'sampler2D':'uniform1iv(location, value)' +}; + +module.exports = generateUniformAccessObject; + +},{}],27:[function(require,module,exports){ + + +var mapSize = function(type) +{ + return GLSL_TO_SIZE[type]; +}; + + +var GLSL_TO_SIZE = { + 'float': 1, + 'vec2': 2, + 'vec3': 3, + 'vec4': 4, + + 'int': 1, + 'ivec2': 2, + 'ivec3': 3, + 'ivec4': 4, + + 'bool': 1, + 'bvec2': 2, + 'bvec3': 3, + 'bvec4': 4, + + 'mat2': 4, + 'mat3': 9, + 'mat4': 16, + + 'sampler2D': 1 +}; + +module.exports = mapSize; + +},{}],28:[function(require,module,exports){ + + +var mapSize = function(gl, type) +{ + if(!GL_TABLE) + { + var typeNames = Object.keys(GL_TO_GLSL_TYPES); + + GL_TABLE = {}; + + for(var i = 0; i < typeNames.length; ++i) + { + var tn = typeNames[i]; + GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; + } + } + + return GL_TABLE[type]; +}; + +var GL_TABLE = null; + +var GL_TO_GLSL_TYPES = { + 'FLOAT': 'float', + 'FLOAT_VEC2': 'vec2', + 'FLOAT_VEC3': 'vec3', + 'FLOAT_VEC4': 'vec4', + + 'INT': 'int', + 'INT_VEC2': 'ivec2', + 'INT_VEC3': 'ivec3', + 'INT_VEC4': 'ivec4', + + 'BOOL': 'bool', + 'BOOL_VEC2': 'bvec2', + 'BOOL_VEC3': 'bvec3', + 'BOOL_VEC4': 'bvec4', + + 'FLOAT_MAT2': 'mat2', + 'FLOAT_MAT3': 'mat3', + 'FLOAT_MAT4': 'mat4', + + 'SAMPLER_2D': 'sampler2D' +}; + +module.exports = mapSize; + },{}],29:[function(require,module,exports){ (function (process){ /*! @@ -6991,7 +7035,7 @@ }()); }).call(this,require('_process')) -},{"_process":19}],30:[function(require,module,exports){ +},{"_process":4}],30:[function(require,module,exports){ var async = require('async'), urlParser = require('url'), Resource = require('./Resource'), @@ -7449,7 +7493,7 @@ Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; -},{"./Resource":31,"async":29,"eventemitter3":26,"url":24}],31:[function(require,module,exports){ +},{"./Resource":31,"async":29,"eventemitter3":11,"url":9}],31:[function(require,module,exports){ var EventEmitter = require('eventemitter3'), _url = require('url'), // tests is CORS is supported in XHR, if not we need to use XDR @@ -8251,7 +8295,7 @@ map[extname] = val; } -},{"eventemitter3":26,"url":24}],32:[function(require,module,exports){ +},{"eventemitter3":11,"url":9}],32:[function(require,module,exports){ module.exports = { // private property @@ -8943,7 +8987,7 @@ Shader.prototype.constructor = Shader; module.exports = Shader; -},{"./const":40,"pixi-gl-core":1}],40:[function(require,module,exports){ +},{"./const":40,"pixi-gl-core":14}],40:[function(require,module,exports){ /** * Constant values used in pixi @@ -10397,7 +10441,7 @@ this.filterArea = null; }; -},{"../math":62,"./Transform":44,"eventemitter3":26}],43:[function(require,module,exports){ +},{"../math":62,"./Transform":44,"eventemitter3":11}],43:[function(require,module,exports){ /** * An observable point is a point that triggers a callback when the point's position is changed. * @@ -12609,7 +12653,7 @@ this.glIndices = null; }; -},{"pixi-gl-core":1}],52:[function(require,module,exports){ +},{"pixi-gl-core":14}],52:[function(require,module,exports){ var Shader = require('../../../Shader'); /** @@ -13047,7 +13091,7 @@ module.exports = buildPoly; -},{"../../../utils":110,"./buildLine":54,"earcut":25}],56:[function(require,module,exports){ +},{"../../../utils":110,"./buildLine":54,"earcut":10}],56:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -13249,7 +13293,7 @@ module.exports = buildRoundedRectangle; -},{"../../../utils":110,"./buildLine":54,"earcut":25}],58:[function(require,module,exports){ +},{"../../../utils":110,"./buildLine":54,"earcut":10}],58:[function(require,module,exports){ /** * @file Main export of the PIXI core library * @author Mat Groves @@ -13346,7 +13390,7 @@ } }); -},{"./Shader":39,"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./display/Transform":44,"./display/TransformStatic":45,"./graphics/Graphics":46,"./graphics/GraphicsData":47,"./graphics/canvas/CanvasGraphicsRenderer":48,"./graphics/webgl/GraphicsRenderer":50,"./math":62,"./renderers/canvas/CanvasRenderer":69,"./renderers/canvas/utils/CanvasRenderTarget":71,"./renderers/webgl/WebGLRenderer":76,"./renderers/webgl/filters/Filter":78,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":81,"./renderers/webgl/managers/WebGLManager":85,"./renderers/webgl/utils/ObjectRenderer":86,"./renderers/webgl/utils/Quad":87,"./renderers/webgl/utils/RenderTarget":88,"./sprites/Sprite":92,"./sprites/canvas/CanvasSpriteRenderer":93,"./sprites/canvas/CanvasTinter":94,"./sprites/webgl/SpriteRenderer":96,"./text/Text":98,"./text/TextStyle":99,"./textures/BaseRenderTexture":100,"./textures/BaseTexture":101,"./textures/RenderTexture":102,"./textures/Texture":103,"./textures/TextureUvs":104,"./textures/VideoBaseTexture":105,"./ticker":107,"./utils":110,"pixi-gl-core":1}],59:[function(require,module,exports){ +},{"./Shader":39,"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./display/Transform":44,"./display/TransformStatic":45,"./graphics/Graphics":46,"./graphics/GraphicsData":47,"./graphics/canvas/CanvasGraphicsRenderer":48,"./graphics/webgl/GraphicsRenderer":50,"./math":62,"./renderers/canvas/CanvasRenderer":69,"./renderers/canvas/utils/CanvasRenderTarget":71,"./renderers/webgl/WebGLRenderer":76,"./renderers/webgl/filters/Filter":78,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":81,"./renderers/webgl/managers/WebGLManager":85,"./renderers/webgl/utils/ObjectRenderer":86,"./renderers/webgl/utils/Quad":87,"./renderers/webgl/utils/RenderTarget":88,"./sprites/Sprite":92,"./sprites/canvas/CanvasSpriteRenderer":93,"./sprites/canvas/CanvasTinter":94,"./sprites/webgl/SpriteRenderer":96,"./text/Text":98,"./text/TextStyle":99,"./textures/BaseRenderTexture":100,"./textures/BaseTexture":101,"./textures/RenderTexture":102,"./textures/Texture":103,"./textures/TextureUvs":104,"./textures/VideoBaseTexture":105,"./ticker":107,"./utils":110,"pixi-gl-core":14}],59:[function(require,module,exports){ // Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16 var ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1]; @@ -14896,7 +14940,7 @@ this._lastObjectRendered = null; }; -},{"../const":40,"../display/Container":41,"../math":62,"../textures/RenderTexture":102,"../utils":110,"eventemitter3":26}],69:[function(require,module,exports){ +},{"../const":40,"../display/Container":41,"../math":62,"../textures/RenderTexture":102,"../utils":110,"eventemitter3":11}],69:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), CanvasMaskManager = require('./utils/CanvasMaskManager'), CanvasRenderTarget = require('./utils/CanvasRenderTarget'), @@ -15841,7 +15885,7 @@ module.exports = TextureManager; -},{"../../const":40,"../../utils":110,"./utils/RenderTarget":88,"pixi-gl-core":1}],76:[function(require,module,exports){ +},{"../../const":40,"../../utils":110,"./utils/RenderTarget":88,"pixi-gl-core":14}],76:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), @@ -16399,7 +16443,7 @@ // this = null; }; -},{"../../const":40,"../../utils":110,"../SystemRenderer":68,"./TextureGarbageCollector":74,"./TextureManager":75,"./WebGLState":77,"./managers/FilterManager":82,"./managers/MaskManager":83,"./managers/StencilManager":84,"./utils/ObjectRenderer":86,"./utils/RenderTarget":88,"./utils/mapWebGLDrawModesToPixi":91,"pixi-gl-core":1}],77:[function(require,module,exports){ +},{"../../const":40,"../../utils":110,"../SystemRenderer":68,"./TextureGarbageCollector":74,"./TextureManager":75,"./WebGLState":77,"./managers/FilterManager":82,"./managers/MaskManager":83,"./managers/StencilManager":84,"./utils/ObjectRenderer":86,"./utils/RenderTarget":88,"./utils/mapWebGLDrawModesToPixi":91,"pixi-gl-core":14}],77:[function(require,module,exports){ var mapWebGLBlendModesToPixi = require('./utils/mapWebGLBlendModesToPixi'); /** @@ -16868,7 +16912,7 @@ module.exports = extractUniformsFromSrc; -},{"pixi-gl-core/lib/shader/defaultValue":10,"pixi-gl-core/lib/shader/mapSize":14}],80:[function(require,module,exports){ +},{"pixi-gl-core/lib/shader/defaultValue":23,"pixi-gl-core/lib/shader/mapSize":27}],80:[function(require,module,exports){ var math = require('../../../math'); /* @@ -17048,7 +17092,6 @@ this.resolution = 1; }; -FilterManager.pool = {}; /** * @class @@ -17074,6 +17117,7 @@ this.shaderCache = {}; // todo add default! + this.pool = {}; } FilterManager.prototype = Object.create(WebGLManager.prototype); @@ -17109,7 +17153,7 @@ destinationFrame.width = sourceFrame.width; destinationFrame.height = sourceFrame.height; - var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, sourceFrame.width, sourceFrame.height, resolution); + var renderTarget = this.getPotRenderTarget(renderer.gl, sourceFrame.width, sourceFrame.height, resolution); currentState.target = target; currentState.filters = filters; @@ -17137,13 +17181,13 @@ if(filters.length === 1) { - filters[0].apply(this, currentState.renderTarget, lastState.renderTarget, true); - FilterManager.freePotRenderTarget(currentState.renderTarget); + filters[0].apply(this, currentState.renderTarget, lastState.renderTarget, false); + this.freePotRenderTarget(currentState.renderTarget); } else { var flip = currentState.renderTarget; - var flop = FilterManager.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var flop = this.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); flop.setFrame(currentState.destinationFrame, currentState.sourceFrame); for (var i = 0; i < filters.length-1; i++) @@ -17155,10 +17199,10 @@ flop = t; } - filters[i].apply(this, flip, lastState.renderTarget, true); + filters[i].apply(this, flip, lastState.renderTarget, false); - FilterManager.freePotRenderTarget(flip); - FilterManager.freePotRenderTarget(flop); + this.freePotRenderTarget(flip); + this.freePotRenderTarget(flop); } this.stackIndex--; @@ -17300,7 +17344,7 @@ FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - var renderTarget = FilterManager.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + var renderTarget = this.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); return renderTarget; @@ -17308,7 +17352,7 @@ FilterManager.prototype.returnRenderTarget = function(renderTarget) { - return FilterManager.freePotRenderTarget(renderTarget); + return this.freePotRenderTarget(renderTarget); }; /* @@ -17344,14 +17388,14 @@ FilterManager.prototype.destroy = function() { this.shaderCache = []; - FilterManager.emptyPool(); + this.emptyPool(); }; //TODO move to a seperate class could be on renderer? //also - could cause issue with multiple contexts? -FilterManager.getPotRenderTarget = function(gl, minWidth, minHeight, resolution) +FilterManager.prototype.getPotRenderTarget = function(gl, minWidth, minHeight, resolution) { //TODO you coud return a bigger texture if there is not one in the pool? minWidth = bitTwiddle.nextPow2(minWidth * resolution); @@ -17360,11 +17404,11 @@ var key = ((minWidth & 0xFFFF) << 16) | ( minHeight & 0xFFFF); // console.log(minWidth + " " + minHeight) - if(!FilterManager.pool[key]) { - FilterManager.pool[key] = []; + if(!this.pool[key]) { + this.pool[key] = []; } - var renderTarget = FilterManager.pool[key].pop() || new RenderTarget(gl, minWidth, minHeight, null, 1); + var renderTarget = this.pool[key].pop() || new RenderTarget(gl, minWidth, minHeight, null, 1); //manually tweak the resolution... //this will not modify the size of the frame buffer, just its resolution. @@ -17375,11 +17419,11 @@ return renderTarget; }; -FilterManager.emptyPool = function() +FilterManager.prototype.emptyPool = function() { - for (var i in FilterManager.pool) + for (var i in this.pool) { - var textures = FilterManager.pool[i]; + var textures = this.pool[i]; if(textures) { for (var j = 0; j < textures.length; j++) @@ -17389,19 +17433,19 @@ } } - FilterManager.pool = {}; + this.pool = {}; }; -FilterManager.freePotRenderTarget = function(renderTarget) +FilterManager.prototype.freePotRenderTarget = function(renderTarget) { var minWidth = renderTarget.size.width * renderTarget.resolution; var minHeight = renderTarget.size.height * renderTarget.resolution; var key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - FilterManager.pool[key].push(renderTarget); + this.pool[key].push(renderTarget); }; -},{"../../../Shader":39,"../../../math":62,"../filters/filterTransforms":80,"../utils/Quad":87,"../utils/RenderTarget":88,"./WebGLManager":85,"bit-twiddle":17}],83:[function(require,module,exports){ +},{"../../../Shader":39,"../../../math":62,"../filters/filterTransforms":80,"../utils/Quad":87,"../utils/RenderTarget":88,"./WebGLManager":85,"bit-twiddle":2}],83:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), AlphaMaskFilter = require('../filters/spriteMask/SpriteMaskFilter'); @@ -17564,10 +17608,11 @@ this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST); - this.renderer.gl.scissor(bounds.x, - renderTarget.root ? renderTarget.size.height - bounds.y - bounds.height : bounds.y, - bounds.width , - bounds.height); + var resolution = this.renderer.resolution; + this.renderer.gl.scissor(bounds.x * resolution, + (renderTarget.root ? renderTarget.size.height - bounds.y - bounds.height : bounds.y) * resolution, + bounds.width * resolution, + bounds.height * resolution); this.scissorRenderTarget = renderTarget; this.scissorData = maskData; @@ -17970,7 +18015,7 @@ module.exports = Quad; -},{"../../../utils/createIndicesForQuads":108,"pixi-gl-core":1}],88:[function(require,module,exports){ +},{"../../../utils/createIndicesForQuads":108,"pixi-gl-core":14}],88:[function(require,module,exports){ var math = require('../../../math'), CONST = require('../../../const'), GLFramebuffer = require('pixi-gl-core').GLFramebuffer; @@ -18296,7 +18341,7 @@ this.texture = null; }; -},{"../../../const":40,"../../../math":62,"pixi-gl-core":1}],89:[function(require,module,exports){ +},{"../../../const":40,"../../../math":62,"pixi-gl-core":14}],89:[function(require,module,exports){ var glCore = require('pixi-gl-core'); var fragTemplate = [ @@ -18377,7 +18422,7 @@ module.exports = checkMaxIfStatmentsInShader; -},{"pixi-gl-core":1}],90:[function(require,module,exports){ +},{"pixi-gl-core":14}],90:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -18971,7 +19016,7 @@ width = texture._frame.width, height = texture._frame.height; - if (texture.orig.width <= 0 || texture.orig.height <= 0) + if (texture.orig.width <= 0 || texture.orig.height <= 0 || !texture.baseTexture.source) { return; } @@ -19750,7 +19795,7 @@ }; -},{"../../const":40,"../../renderers/webgl/WebGLRenderer":76,"../../renderers/webgl/utils/ObjectRenderer":86,"../../renderers/webgl/utils/checkMaxIfStatmentsInShader":89,"../../utils/createIndicesForQuads":108,"./BatchBuffer":95,"./generateMultiTextureShader":97,"bit-twiddle":17,"pixi-gl-core":1}],97:[function(require,module,exports){ +},{"../../const":40,"../../renderers/webgl/WebGLRenderer":76,"../../renderers/webgl/utils/ObjectRenderer":86,"../../renderers/webgl/utils/checkMaxIfStatmentsInShader":89,"../../utils/createIndicesForQuads":108,"./BatchBuffer":95,"./generateMultiTextureShader":97,"bit-twiddle":2,"pixi-gl-core":14}],97:[function(require,module,exports){ var Shader = require('../../Shader'); @@ -19891,6 +19936,14 @@ */ this._styleListener = null; + /** + * Private tracker for the current font. + * + * @member {string} + * @private + */ + this._font = ''; + var texture = Texture.fromCanvas(this.canvas); texture.trim = new math.Rectangle(); Sprite.call(this, texture); @@ -20022,7 +20075,12 @@ return; } var style = this._style; - this.context.font = style.font; + + // build canvas api font setting from invididual components. Convert a numeric style.fontSize to px + var fontSizeString = (typeof style.fontSize === 'number') ? style.fontSize + 'px' : style.fontSize; + this._font = style.fontStyle + ' ' + style.fontVariant + ' ' + style.fontWeight + ' ' + fontSizeString + ' ' + style.fontFamily; + + this.context.font = this._font; // word wrap // preserve original text @@ -20034,7 +20092,7 @@ // calculate text width var lineWidths = new Array(lines.length); var maxLineWidth = 0; - var fontProperties = this.determineFontProperties(style.font); + var fontProperties = this.determineFontProperties(this._font); var i; for (i = 0; i < lines.length; i++) @@ -20074,7 +20132,7 @@ //this.context.fillStyle="#FF0000"; //this.context.fillRect(0, 0, this.canvas.width, this.canvas.height); - this.context.font = style.font; + this.context.font = this._font; this.context.strokeStyle = style.stroke; this.context.lineWidth = style.strokeThickness; this.context.textBaseline = style.textBaseline; @@ -20488,7 +20546,11 @@ * @param [style.dropShadowDistance=5] {number} Set a distance of the drop shadow * @param [style.fill='black'] {string|number|CanvasGradient|CanvasPattern} A canvas fillstyle that will be used on the * text e.g 'red', '#00FF00'. @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} - * @param [style.font='bold 20pt Arial'] {string} The style and size of the font + * @param [style.fontFamily='Arial'] {string} The font family + * @param [style.fontSize=26] {number|string} The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * @param [style.fontStyle='normal'] {string} The font style ('normal', 'italic' or 'oblique') + * @param [style.fontVariant='normal'] {string} The font variant ('normal' or 'small-caps') + * @param [style.fontWeight='normal'] {string} The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') * @param [style.letterSpacing=0] {number} The amount of spacing between letters, default is 0 * @param [style.lineHeight] {number} The line height, a number that represents the vertical space that a letter uses * @param [style.lineJoin='miter'] {string} The lineJoin property sets the type of corner created, it can resolve @@ -20523,7 +20585,11 @@ dropShadowColor: '#000000', dropShadowDistance: 5, fill: 'black', - font: 'bold 20pt Arial', + fontFamily: 'Arial', + fontSize: 26, + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: 'normal', letterSpacing: 0, lineHeight: 0, lineJoin: 'miter', @@ -20687,16 +20753,76 @@ } }, - font: { + fontFamily: { get: function () { - return this._font; + return this._fontFamily; }, - set: function (font) + set: function (fontFamily) { - if (this._font !== font) + if (this.fontFamily !== fontFamily) { - this._font = font; + this._fontFamily = fontFamily; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontSize: { + get: function () + { + return this._fontSize; + }, + set: function (fontSize) + { + if (this._fontSize !== fontSize) + { + this._fontSize = fontSize; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontStyle: { + get: function () + { + return this._fontStyle; + }, + set: function (fontStyle) + { + if (this._fontStyle !== fontStyle) + { + this._fontStyle = fontStyle; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontVariant: { + get: function () + { + return this._fontVariant; + }, + set: function (fontVariant) + { + if (this._fontVariant !== fontVariant) + { + this._fontVariant = fontVariant; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontWeight: { + get: function () + { + return this._fontWeight; + }, + set: function (fontWeight) + { + if (this._fontWeight !== fontWeight) + { + this._fontWeight = fontWeight; this.emit(CONST.TEXT_STYLE_CHANGED); } } @@ -20870,7 +20996,7 @@ } } -},{"../const":40,"../utils":110,"eventemitter3":26}],100:[function(require,module,exports){ +},{"../const":40,"../utils":110,"eventemitter3":11}],100:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), CONST = require('../const'); @@ -21455,7 +21581,7 @@ return baseTexture; }; -},{"../const":40,"../utils":110,"../utils/determineCrossOrigin":109,"bit-twiddle":17,"eventemitter3":26}],102:[function(require,module,exports){ +},{"../const":40,"../utils":110,"../utils/determineCrossOrigin":109,"bit-twiddle":2,"eventemitter3":11}],102:[function(require,module,exports){ var BaseRenderTexture = require('./BaseRenderTexture'), Texture = require('./Texture'); @@ -22078,7 +22204,7 @@ Texture.EMPTY.emit = function() {}; -},{"../math":62,"../utils":110,"./BaseTexture":101,"./TextureUvs":104,"./VideoBaseTexture":105,"eventemitter3":26}],104:[function(require,module,exports){ +},{"../math":62,"../utils":110,"./BaseTexture":101,"./TextureUvs":104,"./VideoBaseTexture":105,"eventemitter3":11}],104:[function(require,module,exports){ /** * A standard object to store the Uvs of a texture @@ -22753,7 +22879,7 @@ module.exports = Ticker; -},{"../const":40,"eventemitter3":26}],107:[function(require,module,exports){ +},{"../const":40,"eventemitter3":11}],107:[function(require,module,exports){ var Ticker = require('./Ticker'); /** @@ -22885,7 +23011,7 @@ module.exports = determineCrossOrigin; -},{"url":24}],110:[function(require,module,exports){ +},{"url":9}],110:[function(require,module,exports){ var CONST = require('../const'); /** @@ -23095,7 +23221,7 @@ BaseTextureCache: {} }; -},{"../const":40,"./pluginTarget":112,"eventemitter3":26}],111:[function(require,module,exports){ +},{"../const":40,"./pluginTarget":112,"eventemitter3":11}],111:[function(require,module,exports){ var Device = require('ismobilejs'); @@ -23116,7 +23242,7 @@ }; module.exports = maxRecommendedTextures; -},{"ismobilejs":27}],112:[function(require,module,exports){ +},{"ismobilejs":12}],112:[function(require,module,exports){ /** * Mixins functionality to make an object have "plugins". * @@ -23192,7 +23318,8 @@ mesh = require('./mesh'), particles = require('./particles'), extras = require('./extras'), - filters = require('./filters'); + filters = require('./filters'), + CONST = require('./core/const'); // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -23569,6 +23696,90 @@ warn('setStyle is now deprecated, please use the style property, e.g : myText.style = style;'); }; +Object.defineProperties(core.TextStyle.prototype, { + font: { + get: function () + { + warn('text style property \'font\' is now deprecated, please use the \'fontFamily\',\'fontSize\',fontStyle\',\'fontVariant\' and \'fontWeight\' properties from now on'); + var fontSizeString = (typeof this._fontSize === 'number') ? this._fontSize + 'px' : this._fontSize; + return this._fontStyle + ' ' + this._fontVariant + ' ' + this._fontWeight + ' ' + fontSizeString + ' ' + this._fontFamily; + }, + set: function (font) + { + warn('text style property \'font\' is now deprecated, please use the \'fontFamily\',\'fontSize\',fontStyle\',\'fontVariant\' and \'fontWeight\' properties from now on'); + + // can work out fontStyle from search of whole string + if ( font.indexOf('italic') > 1 ) + { + this._fontStyle = 'italic'; + } + else if ( font.indexOf('oblique') > -1 ) + { + this._fontStyle = 'oblique'; + } + else + { + this._fontStyle = 'normal'; + } + + // can work out fontVariant from search of whole string + if ( font.indexOf('small-caps') > -1 ) + { + this._fontVariant = 'small-caps'; + } + else + { + this._fontVariant = 'normal'; + } + + // fontWeight and fontFamily are tricker to find, but it's easier to find the fontSize due to it's units + var splits = font.split(' '); + var i; + var fontSizeIndex = -1; + + this._fontSize = 26; + for ( i = 0; i < splits.length; ++i ) + { + if ( splits[i].match( /(px|pt|em|%)/ ) ) + { + fontSizeIndex = i; + this._fontSize = splits[i]; + break; + } + } + + // we can now search for fontWeight as we know it must occur before the fontSize + this._fontWeight = 'normal'; + for ( i = 0; i < fontSizeIndex; ++i ) + { + if ( splits[i].match( /(bold|bolder|lighter|100|200|300|400|500|600|700|800|900)/ ) ) + { + this._fontWeight = splits[i]; + break; + } + } + + // and finally join everything together after the fontSize in case the font family has multiple words + if ( fontSizeIndex > -1 && fontSizeIndex < splits.length-1 ) + { + this._fontFamily = ''; + for ( i = fontSizeIndex + 1; i < splits.length; ++i ) + { + this._fontFamily += splits[i] + ' '; + } + + this._fontFamily = this._fontFamily.slice(0, -1); + } + else + { + this._fontFamily = 'Arial'; + } + + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } +} ); + /** * @method * @name PIXI.Texture#setFrame @@ -23647,7 +23858,7 @@ }; -},{"./core":58,"./extras":123,"./filters":135,"./mesh":150,"./particles":153}],114:[function(require,module,exports){ +},{"./core":58,"./core/const":40,"./extras":123,"./filters":135,"./mesh":150,"./particles":153}],114:[function(require,module,exports){ var core = require('../../core'), tempRect = new core.Rectangle(); @@ -28149,7 +28360,7 @@ }; }; -},{"../core":58,"../extras":123,"path":18,"resource-loader":33}],143:[function(require,module,exports){ +},{"../core":58,"../extras":123,"path":3,"resource-loader":33}],143:[function(require,module,exports){ /** * @file Main export of the PIXI loaders library * @author Mat Groves @@ -28349,7 +28560,7 @@ }; }; -},{"../core":58,"async":16,"path":18,"resource-loader":33}],146:[function(require,module,exports){ +},{"../core":58,"async":1,"path":3,"resource-loader":33}],146:[function(require,module,exports){ var core = require('../core'); module.exports = function () @@ -28908,7 +29119,7 @@ TRIANGLES: 1 }; -},{"../core":58,"./webgl/MeshShader":151,"pixi-gl-core":1}],148:[function(require,module,exports){ +},{"../core":58,"./webgl/MeshShader":151,"pixi-gl-core":14}],148:[function(require,module,exports){ var Mesh = require('./Mesh'); /** @@ -29882,7 +30093,7 @@ this.staticBuffer.destroy(); }; -},{"../../core/utils/createIndicesForQuads":108,"pixi-gl-core":1}],155:[function(require,module,exports){ +},{"../../core/utils/createIndicesForQuads":108,"pixi-gl-core":14}],155:[function(require,module,exports){ var core = require('../../core'), ParticleShader = require('./ParticleShader'), ParticleBuffer = require('./ParticleBuffer'); @@ -30406,7 +30617,7 @@ Object.assign = require('object-assign'); } -},{"object-assign":28}],159:[function(require,module,exports){ +},{"object-assign":13}],159:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); diff --git a/bin/pixi.js b/bin/pixi.js index 7cd7492..79c8df2 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -1,1532 +1,4 @@ (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= data.byteLength) - { - gl.bufferSubData(this.type, offset, data); - } - else - { - gl.bufferData(this.type, data, this.drawType); - } - - this.data = data; -}; -/** - * Binds the buffer - * - */ -Buffer.prototype.bind = function() -{ - var gl = this.gl; - gl.bindBuffer(this.type, this.buffer); -}; - -Buffer.createVertexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); -}; - -Buffer.createIndexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); -}; - -Buffer.create = function(gl, type, data, drawType) -{ - return new Buffer(gl, type, drawType); -}; - -/** - * Destroys the buffer - * - */ -Buffer.prototype.destroy = function(){ - this.gl.deleteBuffer(this.buffer); -}; - -module.exports = Buffer; - -},{}],3:[function(require,module,exports){ - -var Texture = require('./GLTexture'); - -/** - * Helper class to create a webGL Framebuffer - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - */ -var Framebuffer = function(gl, width, height) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * The frame buffer - * - * @member {WebGLFramebuffer} - */ - this.framebuffer = gl.createFramebuffer(); - - /** - * The stencil buffer - * - * @member {WebGLRenderbuffer} - */ - this.stencil = null; - - /** - * The stencil buffer - * - * @member {GLTexture} - */ - this.texture = null; - - /** - * The width of the drawing area of the buffer - * - * @member {Number} - */ - this.width = width || 100; - /** - * The height of the drawing area of the buffer - * - * @member {Number} - */ - this.height = height || 100; -}; - -/** - * Adds a texture to the frame buffer - * @param texture {GLTexture} - */ -Framebuffer.prototype.enableTexture = function(texture) -{ - var gl = this.gl; - - this.texture = texture || new Texture(gl); - - this.texture.bind(); - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - this.bind(); - - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); -}; - -/** - * Initialises the stencil buffer - * @mat maybe you can come up with a better explaination - */ -Framebuffer.prototype.enableStencil = function() -{ - if(this.stencil)return; - - var gl = this.gl; - - this.stencil = gl.createRenderbuffer(); - - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - - // TODO.. this is depth AND stencil? - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); -}; - -/** - * Erases the drawing area and fills it with a colour - * @param r {Number} the red value of the clearing colour - * @param g {Number} the green value of the clearing colour - * @param b {Number} the blue value of the clearing colour - * @param a {Number} the alpha value of the clearing colour - */ -Framebuffer.prototype.clear = function( r, g, b, a ) -{ - this.bind(); - - var gl = this.gl; - - gl.clearColor(r, g, b, a); - gl.clear(gl.COLOR_BUFFER_BIT); -}; - -/** - * Binds the frame buffer to the WebGL context - */ -Framebuffer.prototype.bind = function() -{ - var gl = this.gl; - - if(this.texture) - { - this.texture.unbind(); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); -}; - -/** - * Unbinds the frame buffer to the WebGL context - */ -Framebuffer.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, null ); -}; -/** - * Resizes the drawing area of the buffer to the given width and height - * @param width {Number} the new width - * @param height {Number} the new height - */ -Framebuffer.prototype.resize = function(width, height) -{ - var gl = this.gl; - - this.width = width; - this.height = height; - - if ( this.texture ) - { - this.texture.uploadData(null, width, height); - } - - if ( this.stencil ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); - } -}; - -/** - * Destroys this buffer - */ -Framebuffer.prototype.destroy = function() -{ - var gl = this.gl; - - //TODO - if(this.texture) - { - this.texture.destroy(); - } - - gl.deleteFramebuffer(this.framebuffer); - - this.gl = null; - - this.stencil = null; - this.texture = null; -}; - -/** - * Creates a frame buffer with a texture containing the given data - * @mat can you confirm ? :) - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createRGBA = function(gl, width, height, data) -{ - var texture = Texture.fromData(gl, null, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); - - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture); - - fbo.unbind(); - - return fbo; -}; - -/** - * Creates a frame buffer with a texture containing the given data - * @mat not sure what the difference is with the method above ? - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createFloat32 = function(gl, width, height, data) -{ - // create a new texture.. - var texture = new Texture.fromData(gl, data, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); - - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture); - - fbo.unbind(); - - return fbo; -}; - -module.exports = Framebuffer; - -},{"./GLTexture":5}],4:[function(require,module,exports){ - -var compileProgram = require('./shader/compileProgram'), - extractAttributes = require('./shader/extractAttributes'), - extractUniforms = require('./shader/extractUniforms'), - generateUniformAccessObject = require('./shader/generateUniformAccessObject'); - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - */ -var Shader = function(gl, vertexSrc, fragmentSrc) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc); - - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - var uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject( gl, uniformData ); -}; -/** - * Uses this shader - */ -Shader.prototype.bind = function() -{ - this.gl.useProgram(this.program); -}; - -/** - * Destroys this shader - * TODO - */ -Shader.prototype.destroy = function() -{ - var gl = this.gl; -}; - -module.exports = Shader; - -},{"./shader/compileProgram":9,"./shader/extractAttributes":11,"./shader/extractUniforms":12,"./shader/generateUniformAccessObject":13}],5:[function(require,module,exports){ - -/** - * Helper class to create a WebGL Texture - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL context - * @param width {number} the width of the texture - * @param height {number} the height of the texture - * @param format {number} the pixel format of the texture. defaults to gl.RGBA - * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE - */ -var Texture = function(gl, width, height, format, type) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - - /** - * The WebGL texture - * - * @member {WebGLTexture} - */ - this.texture = gl.createTexture(); - - /** - * If mipmapping was used for this texture, enable and disable with enableMipmap() - * - * @member {Boolean} - */ - // some settings.. - this.mipmap = false; - - - /** - * Set to true to enable pre-multiplied alpha - * - * @member {Boolean} - */ - this.premultiplyAlpha = false; - - /** - * The width of texture - * - * @member {Number} - */ - this.width = width || 0; - /** - * The height of texture - * - * @member {Number} - */ - this.height = height || 0; - - /** - * The pixel format of the texture. defaults to gl.RGBA - * - * @member {Number} - */ - this.format = format || gl.RGBA; - - /** - * The gl type of the texture. defaults to gl.UNSIGNED_BYTE - * - * @member {Number} - */ - this.type = type || gl.UNSIGNED_BYTE; - - -}; - -/** - * Uploads this texture to the GPU - * @param source {HTMLImageElement|ImageData|HTMLVideoElement} the source image of the texture - */ -Texture.prototype.upload = function(source) -{ - this.bind(); - - var gl = this.gl; - - // if the source is a video, we need to use the videoWidth / videoHeight properties as width / height will be incorrect. - this.width = source.videoWidth || source.width; - this.height = source.videoHeight || source.height; - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); -}; - -var FLOATING_POINT_AVAILABLE = false; - -/** - * Use a data source and uploads this texture to the GPU - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.prototype.uploadData = function(data, width, height) -{ - this.bind(); - - var gl = this.gl; - - this.width = width || this.width; - this.height = height || this.height; - - if(data instanceof Float32Array) - { - if(!FLOATING_POINT_AVAILABLE) - { - var ext = gl.getExtension("OES_texture_float"); - - if(ext) - { - FLOATING_POINT_AVAILABLE = true; - } - else - { - throw new Error('floating point textures not available'); - } - } - - this.type = gl.FLOAT; - } - else - { - // TODO support for other types - this.type = gl.UNSIGNED_BYTE; - } - - - - // what type of data? - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); - -}; - -/** - * Binds the texture - * @param location {@mat} - */ -Texture.prototype.bind = function(location) -{ - var gl = this.gl; - - if(location !== undefined) - { - gl.activeTexture(gl.TEXTURE0 + location); - } - - gl.bindTexture(gl.TEXTURE_2D, this.texture); -}; - -/** - * Unbinds the texture - */ -Texture.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, null); -}; - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.minFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - if(this.mipmap) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); - } -}; - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.magFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); -}; - -/** - * Enables mipmapping - */ -Texture.prototype.enableMipmap = function() -{ - var gl = this.gl; - - this.bind(); - - this.mipmap = true; - - gl.generateMipmap(gl.TEXTURE_2D); -}; - -/** - * Enables linear filtering - */ -Texture.prototype.enableLinearScaling = function() -{ - this.minFilter(true); - this.magFilter(true); -}; - -/** - * Enables nearest neighbour interpolation - */ -Texture.prototype.enableNearestScaling = function() -{ - this.minFilter(false); - this.magFilter(false); -}; - -/** - * Enables clamping on the texture so WebGL will not repeat it - */ -Texture.prototype.enableWrapClamp = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); -}; - -/** - * Enable tiling on the texture - */ -Texture.prototype.enableWrapRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); -}; - -/** - * @mat - */ -Texture.prototype.enableWrapMirrorRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); -}; - - -/** - * Destroys this texture - */ -Texture.prototype.destroy = function() -{ - var gl = this.gl; - //TODO - gl.deleteTexture(this.texture); -}; - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param source {HTMLImageElement|ImageData} the source image of the texture - * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha - */ -Texture.fromSource = function(gl, source, premultiplyAlpha) -{ - var texture = new Texture(gl); - texture.premultiplyAlpha = premultiplyAlpha || false; - texture.upload(source); - - return texture; -}; - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.fromData = function(gl, data, width, height) -{ - //console.log(data, width, height); - var texture = new Texture(gl); - texture.uploadData(data, width, height); - - return texture; -}; - - -module.exports = Texture; - -},{}],6:[function(require,module,exports){ - -// state object// -var setVertexAttribArrays = require( './setVertexAttribArrays' ); - -/** - * Helper class to work with WebGL VertexArrayObjects (vaos) - * Only works if WebGL extensions are enabled (they usually are) - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - */ -function VertexArrayObject(gl, state) -{ - - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); - - this.nativeState = state; - - if(this.nativeVaoExtension) - { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - - var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - - // VAO - overwrite the state.. - this.nativeState = { - tempAttribState: new Array(maxAttribs), - attribState: new Array(maxAttribs) - }; - } - - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * An array of attributes ? @mat - * - * @member {Array} - */ - this.attributes = []; - - /** - * @mat - * - * @member {Array} - */ - this.indexBuffer = null; - - /** - * A boolean flag - * - * @member {Boolean} - */ - this.dirty = false; -} - -VertexArrayObject.prototype.constructor = VertexArrayObject; -module.exports = VertexArrayObject; - - -/** - * Binds the buffer - */ -VertexArrayObject.prototype.bind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - - if(this.dirty) - { - this.dirty = false; - this.activate(); - } - } - else - { - - this.activate(); - } - - return this; -}; - -/** - * Unbinds the buffer - */ -VertexArrayObject.prototype.unbind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(null); - } - - return this; -}; - -/** - * Uses this vao - */ -VertexArrayObject.prototype.activate = function() -{ - - var gl = this.gl; - var lastBuffer = null; - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - - if(lastBuffer !== attrib.buffer) - { - attrib.buffer.bind(); - lastBuffer = attrib.buffer; - } - - //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.start || 0); - - - } - - setVertexAttribArrays(gl, this.attributes, this.nativeState); - - this.indexBuffer.bind(); - - return this; -}; - -/** - * - * @param buffer {WebGLBuffer} - * @param attribute {[type]} - * @param type {[type]} - * @param normalized {[type]} - * @param stride {Number} - * @param start {Number} - */ -VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) -{ - this.attributes.push({ - buffer: buffer, - attribute: attribute, - - location: attribute.location, - type: type || this.gl.FLOAT, - normalized: normalized || false, - stride: stride || 0, - start: start || 0 - }); - - this.dirty = true; - - return this; -}; - -/** - * - * @param buffer {WebGLBuffer} - * @param options {Object} - */ -VertexArrayObject.prototype.addIndex = function(buffer, options) -{ - this.indexBuffer = buffer; - - this.dirty = true; - - return this; -}; - -/** - * Unbinds this vao and disables it - */ -VertexArrayObject.prototype.clear = function() -{ - var gl = this.gl; - - // TODO - should this function unbind after clear? - // for now, no but lets see what happens in the real world! - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - } - - this.attributes.length = 0; - this.indexBuffer = null; - - return this; -}; - -/** - * @mat - * @param type {Number} - * @param size {Number} - * @param start {Number} - */ -VertexArrayObject.prototype.draw = function(type, size, start) -{ - var gl = this.gl; - gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); - - return this; -}; - -/** - * Destroy this vao - */ -VertexArrayObject.prototype.destroy = function() -{ - // lose references - this.gl = null; - this.indexBuffer = null; - this.attributes = null; - this.nativeState = null; - - if(this.nativeVao) - { - this.nativeVaoExtension.deleteVertexArrayOES(this.nativeVao); - } - - this.nativeVaoExtension = null; - this.nativeVao = null; -}; - -},{"./setVertexAttribArrays":8}],7:[function(require,module,exports){ - -/** - * Helper class to create a webGL Context - * - * @class - * @memberof pixi.gl - * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from - * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, - * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available - * @return {WebGLRenderingContext} the WebGL context - */ -var createContext = function(canvas, options) -{ - var gl = canvas.getContext('webgl', options) || - canvas.getContext('experimental-webgl', options); - - if (!gl) - { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); - } - - return gl; -}; - -module.exports = createContext; - -},{}],8:[function(require,module,exports){ -var GL_MAP = {}; - -/** - * @mat - * @param gl {WebGLRenderingContext} The current WebGL context - * @param attribs {[type]} - */ -var setVertexAttribArrays = function (gl, attribs, state) -{ - var i; - if(state) - { - var tempAttribState = state.tempAttribState, - attribState = state.attribState; - - for (i = 0; i < tempAttribState.length; i++) - { - tempAttribState[i] = false; - } - - // set the new attribs - for (i = 0; i < attribs.length; i++) - { - tempAttribState[attribs[i].attribute.location] = true; - } - - for (i = 0; i < attribState.length; i++) - { - if (attribState[i] !== tempAttribState[i]) - { - attribState[i] = tempAttribState[i]; - - if (state.attribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } - } - } - - } - else - { - for (i = 0; i < attribs.length; i++) - { - var attrib = attribs[i]; - gl.enableVertexAttribArray(attrib.attribute.location); - } - } -}; - -module.exports = setVertexAttribArrays; - -},{}],9:[function(require,module,exports){ - -/** - * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @return {WebGLProgram} the shader program - */ -var compileProgram = function(gl, vertexSrc, fragmentSrc) -{ - var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); - var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); - - var program = gl.createProgram(); - - gl.attachShader(program, glVertShader); - gl.attachShader(program, glFragShader); - gl.linkProgram(program); - - // if linking fails, then log and cleanup - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) - { - console.error('Pixi.js Error: Could not initialize shader.'); - console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); - console.error('gl.getError()', gl.getError()); - - // if there is a program info log, log it - if (gl.getProgramInfoLog(program) !== '') - { - console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); - } - - gl.deleteProgram(program); - program = null; - } - - // clean up some shaders - gl.deleteShader(glVertShader); - gl.deleteShader(glFragShader); - - return program; -}; - -/** - * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @return {WebGLShader} the shader - */ -var compileShader = function (gl, type, src) -{ - var shader = gl.createShader(type); - - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) - { - console.log(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; -}; - -module.exports = compileProgram; - -},{}],10:[function(require,module,exports){ - - -var defaultValue = function(type, size) -{ - switch (type) - { - case 'float': - return 0; - - case 'vec2': - return new Float32Array(2 * size); - - case 'vec3': - return new Float32Array(3 * size); - - case 'vec4': - return new Float32Array(4 * size); - - case 'int': - case 'sampler2D': - return 0; - - case 'ivec2': - return new Int32Array(2 * size); - - case 'ivec3': - return new Int32Array(3 * size); - - case 'ivec4': - return new Int32Array(4 * size); - - case 'bool': - return false; - - case 'bvec2': - - return booleanArray( 2 * size); - - case 'bvec3': - return booleanArray(3 * size); - - case 'bvec4': - return booleanArray(4 * size); - - case 'mat2': - return new Float32Array([1, 0, - 0, 1]); - - case 'mat3': - return new Float32Array([1, 0, 0, - 0, 1, 0, - 0, 0, 1]); - - case 'mat4': - return new Float32Array([1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]); - } -}; - -var booleanArray = function(size) -{ - var array = new Array(size); - - for (var i = 0; i < array.length; i++) - { - array[i] = false; - } - - return array; -}; - -module.exports = defaultValue; - -},{}],11:[function(require,module,exports){ - -var mapType = require('./mapType'); -var mapSize = require('./mapSize'); - -/** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} - */ -var extractAttributes = function(gl, program) -{ - var attributes = {}; - - var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); - - for (var i = 0; i < totalAttributes; i++) - { - var attribData = gl.getActiveAttrib(program, i); - var type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type:type, - size:mapSize(type), - location:gl.getAttribLocation(program, attribData.name), - //TODO - make an attribute object - pointer: pointer - }; - } - - return attributes; -}; - -var pointer = function(type, normalized, stride, start){ - // console.log(this.location) - gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); -}; - -module.exports = extractAttributes; - -},{"./mapSize":14,"./mapType":15}],12:[function(require,module,exports){ -var mapType = require('./mapType'); -var defaultValue = require('./defaultValue'); - -/** - * Extracts the uniforms - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -var extractUniforms = function(gl, program) -{ - var uniforms = {}; - - var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); - - for (var i = 0; i < totalUniforms; i++) - { - var uniformData = gl.getActiveUniform(program, i); - var name = uniformData.name.replace(/\[.*?\]/, ""); - var type = mapType(gl, uniformData.type ); - - uniforms[name] = { - type:type, - size:uniformData.size, - location:gl.getUniformLocation(program, name), - value:defaultValue(type, uniformData.size) - }; - } - - return uniforms; -}; - -module.exports = extractUniforms; - -},{"./defaultValue":10,"./mapType":15}],13:[function(require,module,exports){ -/** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param uniforms {Array} @mat ? - * @return attributes {Object} - */ -var generateUniformAccessObject = function(gl, uniformData) -{ - // this is the object we will be sending back. - // an object hierachy will be created for structs - var uniforms = {data:{}}; - - uniforms.gl = gl; - - var uniformKeys= Object.keys(uniformData); - - for (var i = 0; i < uniformKeys.length; i++) - { - var fullName = uniformKeys[i]; - - var nameTokens = fullName.split('.'); - var name = nameTokens[nameTokens.length - 1]; - - var uniformGroup = getUniformGroup(nameTokens, uniforms); - - var uniform = uniformData[fullName]; - uniformGroup.data[name] = uniform; - - uniformGroup.gl = gl; - - Object.defineProperty(uniformGroup, name, { - get: generateGetter(name), - set: generateSetter(name, uniform) - }); - } - - return uniforms; -}; - -var generateGetter = function(name) -{ - var template = getterTemplate.replace('%%', name); - return new Function(template); // jshint ignore:line -}; - -var generateSetter = function(name, uniform) -{ - var template = setterTemplate.replace(/%%/g, name); - var setTemplate; - - if(uniform.size === 1) - { - setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; - } - else - { - setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; - } - - if(setTemplate) - { - template += "\nthis.gl." + setTemplate + ";"; - } - - return new Function('value', template); // jshint ignore:line -}; - -var getUniformGroup = function(nameTokens, uniform) -{ - var cur = uniform; - - for (var i = 0; i < nameTokens.length - 1; i++) - { - var o = cur[nameTokens[i]] || {data:{}}; - cur[nameTokens[i]] = o; - cur = o; - } - - return cur; -}; - -var getterTemplate = [ - 'return this.data.%%.value;', -].join('\n'); - -var setterTemplate = [ - 'this.data.%%.value = value;', - 'var location = this.data.%%.location;' -].join('\n'); - - -var GLSL_TO_SINGLE_SETTERS = { - - 'float': 'uniform1f(location, value)', - - 'vec2': 'uniform2f(location, value[0], value[1])', - 'vec3': 'uniform3f(location, value[0], value[1], value[2])', - 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', - - 'int': 'uniform1i(location, value)', - 'ivec2': 'uniform2i(location, value[0], value[1])', - 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', - 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'bool': 'uniform1i(location, value)', - 'bvec2': 'uniform2i(location, value[0], value[1])', - 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', - 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'mat2': 'uniformMatrix2fv(location, false, value)', - 'mat3': 'uniformMatrix3fv(location, false, value)', - 'mat4': 'uniformMatrix4fv(location, false, value)', - - 'sampler2D':'uniform1i(location, value)' -}; - -var GLSL_TO_ARRAY_SETTERS = { - - 'float': 'uniform1fv(location, value)', - - 'vec2': 'uniform2fv(location, value)', - 'vec3': 'uniform3fv(location, value)', - 'vec4': 'uniform4fv(location, value)', - - 'int': 'uniform1iv(location, value)', - 'ivec2': 'uniform2iv(location, value)', - 'ivec3': 'uniform3iv(location, value)', - 'ivec4': 'uniform4iv(location, value)', - - 'bool': 'uniform1iv(location, value)', - 'bvec2': 'uniform2iv(location, value)', - 'bvec3': 'uniform3iv(location, value)', - 'bvec4': 'uniform4iv(location, value)', - - 'sampler2D':'uniform1iv(location, value)' -}; - -module.exports = generateUniformAccessObject; - -},{}],14:[function(require,module,exports){ - - -var mapSize = function(type) -{ - return GLSL_TO_SIZE[type]; -}; - - -var GLSL_TO_SIZE = { - 'float': 1, - 'vec2': 2, - 'vec3': 3, - 'vec4': 4, - - 'int': 1, - 'ivec2': 2, - 'ivec3': 3, - 'ivec4': 4, - - 'bool': 1, - 'bvec2': 2, - 'bvec3': 3, - 'bvec4': 4, - - 'mat2': 4, - 'mat3': 9, - 'mat4': 16, - - 'sampler2D': 1 -}; - -module.exports = mapSize; - -},{}],15:[function(require,module,exports){ - - -var mapSize = function(gl, type) -{ - if(!GL_TABLE) - { - var typeNames = Object.keys(GL_TO_GLSL_TYPES); - - GL_TABLE = {}; - - for(var i = 0; i < typeNames.length; ++i) - { - var tn = typeNames[i]; - GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; - } - } - - return GL_TABLE[type]; -}; - -var GL_TABLE = null; - -var GL_TO_GLSL_TYPES = { - 'FLOAT': 'float', - 'FLOAT_VEC2': 'vec2', - 'FLOAT_VEC3': 'vec3', - 'FLOAT_VEC4': 'vec4', - - 'INT': 'int', - 'INT_VEC2': 'ivec2', - 'INT_VEC3': 'ivec3', - 'INT_VEC4': 'ivec4', - - 'BOOL': 'bool', - 'BOOL_VEC2': 'bvec2', - 'BOOL_VEC3': 'bvec3', - 'BOOL_VEC4': 'bvec4', - - 'FLOAT_MAT2': 'mat2', - 'FLOAT_MAT3': 'mat3', - 'FLOAT_MAT4': 'mat4', - - 'SAMPLER_2D': 'sampler2D' -}; - -module.exports = mapSize; - -},{}],16:[function(require,module,exports){ (function (process,global){ /*! * async @@ -2795,7 +1267,7 @@ }()); }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":19}],17:[function(require,module,exports){ +},{"_process":4}],2:[function(require,module,exports){ /** * Bit twiddling hacks for JavaScript. * @@ -3001,7 +1473,7 @@ } -},{}],18:[function(require,module,exports){ +},{}],3:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -3229,7 +1701,7 @@ ; }).call(this,require('_process')) -},{"_process":19}],19:[function(require,module,exports){ +},{"_process":4}],4:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -3322,7 +1794,7 @@ }; process.umask = function() { return 0; }; -},{}],20:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ (function (global){ /*! https://mths.be/punycode v1.4.0 by @mathias */ ;(function(root) { @@ -3859,7 +2331,7 @@ }(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],21:[function(require,module,exports){ +},{}],6:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -3945,7 +2417,7 @@ return Object.prototype.toString.call(xs) === '[object Array]'; }; -},{}],22:[function(require,module,exports){ +},{}],7:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -4032,13 +2504,13 @@ return res; }; -},{}],23:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ 'use strict'; exports.decode = exports.parse = require('./decode'); exports.encode = exports.stringify = require('./encode'); -},{"./decode":21,"./encode":22}],24:[function(require,module,exports){ +},{"./decode":6,"./encode":7}],9:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -4747,7 +3219,7 @@ return arg == null; } -},{"punycode":20,"querystring":23}],25:[function(require,module,exports){ +},{"punycode":5,"querystring":8}],10:[function(require,module,exports){ 'use strict'; module.exports = earcut; @@ -5393,7 +3865,7 @@ return result; }; -},{}],26:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ 'use strict'; var has = Object.prototype.hasOwnProperty; @@ -5684,7 +4156,7 @@ module.exports = EventEmitter; } -},{}],27:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ /** * isMobile.js v0.4.0 * @@ -5823,9 +4295,9 @@ })(this); -},{}],28:[function(require,module,exports){ -/* eslint-disable no-unused-vars */ +},{}],13:[function(require,module,exports){ 'use strict'; +/* eslint-disable no-unused-vars */ var hasOwnProperty = Object.prototype.hasOwnProperty; var propIsEnumerable = Object.prototype.propertyIsEnumerable; @@ -5837,7 +4309,51 @@ return Object(val); } -module.exports = Object.assign || function (target, source) { +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } + + return true; + } catch (e) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} + +module.exports = shouldUseNative() ? Object.assign : function (target, source) { var from; var to = toObject(target); var symbols; @@ -5864,6 +4380,1534 @@ return to; }; +},{}],14:[function(require,module,exports){ + + +module.exports = { + + createContext: require('./lib/createContext'), + setVertexAttribArrays: require('./lib/setVertexAttribArrays'), + + GLBuffer: require('./lib/GLBuffer'), + GLFramebuffer: require('./lib/GLFramebuffer'), + GLShader: require('./lib/GLShader'), + GLTexture: require('./lib/GLTexture'), + + VertexArrayObject: require('./lib/VertexArrayObject') + +}; +},{"./lib/GLBuffer":15,"./lib/GLFramebuffer":16,"./lib/GLShader":17,"./lib/GLTexture":18,"./lib/VertexArrayObject":19,"./lib/createContext":20,"./lib/setVertexAttribArrays":21}],15:[function(require,module,exports){ +var EMPTY_ARRAY_BUFFER = new ArrayBuffer(0); + +/** + * Helper class to create a webGL buffer + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param type {gl.ARRAY_BUFFER | gl.ELEMENT_ARRAY_BUFFER} @mat + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + * @param drawType {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + */ +var Buffer = function(gl, type, data, drawType) +{ + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The WebGL buffer, created upon instantiation + * + * @member {WebGLBuffer} + */ + this.buffer = gl.createBuffer(); + + /** + * The type of the buffer + * + * @member {gl.ARRAY_BUFFER || gl.ELEMENT_ARRAY_BUFFER} + */ + this.type = type || gl.ARRAY_BUFFER; + + /** + * The draw type of the buffer + * + * @member {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + */ + this.drawType = drawType || gl.STATIC_DRAW; + + /** + * The data in the buffer, as a typed array + * + * @member {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} + */ + this.data = EMPTY_ARRAY_BUFFER; + + if(data) + { + this.upload(data); + } +}; + +/** + * Uploads the buffer to the GPU + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data to upload + * @param offset {Number} if only a subset of the data should be uploaded, this is the amount of data to subtract + * @param dontBind {Boolean} whether to bind the buffer before uploading it + */ +Buffer.prototype.upload = function(data, offset, dontBind) +{ + // todo - needed? + if(!dontBind) this.bind(); + + var gl = this.gl; + + data = data || this.data; + offset = offset || 0; + + if(this.data.byteLength >= data.byteLength) + { + gl.bufferSubData(this.type, offset, data); + } + else + { + gl.bufferData(this.type, data, this.drawType); + } + + this.data = data; +}; +/** + * Binds the buffer + * + */ +Buffer.prototype.bind = function() +{ + var gl = this.gl; + gl.bindBuffer(this.type, this.buffer); +}; + +Buffer.createVertexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); +}; + +Buffer.createIndexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); +}; + +Buffer.create = function(gl, type, data, drawType) +{ + return new Buffer(gl, type, drawType); +}; + +/** + * Destroys the buffer + * + */ +Buffer.prototype.destroy = function(){ + this.gl.deleteBuffer(this.buffer); +}; + +module.exports = Buffer; + +},{}],16:[function(require,module,exports){ + +var Texture = require('./GLTexture'); + +/** + * Helper class to create a webGL Framebuffer + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + */ +var Framebuffer = function(gl, width, height) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The frame buffer + * + * @member {WebGLFramebuffer} + */ + this.framebuffer = gl.createFramebuffer(); + + /** + * The stencil buffer + * + * @member {WebGLRenderbuffer} + */ + this.stencil = null; + + /** + * The stencil buffer + * + * @member {GLTexture} + */ + this.texture = null; + + /** + * The width of the drawing area of the buffer + * + * @member {Number} + */ + this.width = width || 100; + /** + * The height of the drawing area of the buffer + * + * @member {Number} + */ + this.height = height || 100; +}; + +/** + * Adds a texture to the frame buffer + * @param texture {GLTexture} + */ +Framebuffer.prototype.enableTexture = function(texture) +{ + var gl = this.gl; + + this.texture = texture || new Texture(gl); + + this.texture.bind(); + + //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + this.bind(); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); +}; + +/** + * Initialises the stencil buffer + * @mat maybe you can come up with a better explaination + */ +Framebuffer.prototype.enableStencil = function() +{ + if(this.stencil)return; + + var gl = this.gl; + + this.stencil = gl.createRenderbuffer(); + + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + + // TODO.. this is depth AND stencil? + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); +}; + +/** + * Erases the drawing area and fills it with a colour + * @param r {Number} the red value of the clearing colour + * @param g {Number} the green value of the clearing colour + * @param b {Number} the blue value of the clearing colour + * @param a {Number} the alpha value of the clearing colour + */ +Framebuffer.prototype.clear = function( r, g, b, a ) +{ + this.bind(); + + var gl = this.gl; + + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT); +}; + +/** + * Binds the frame buffer to the WebGL context + */ +Framebuffer.prototype.bind = function() +{ + var gl = this.gl; + + if(this.texture) + { + this.texture.unbind(); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); +}; + +/** + * Unbinds the frame buffer to the WebGL context + */ +Framebuffer.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, null ); +}; +/** + * Resizes the drawing area of the buffer to the given width and height + * @param width {Number} the new width + * @param height {Number} the new height + */ +Framebuffer.prototype.resize = function(width, height) +{ + var gl = this.gl; + + this.width = width; + this.height = height; + + if ( this.texture ) + { + this.texture.uploadData(null, width, height); + } + + if ( this.stencil ) + { + // update the stencil buffer width and height + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + } +}; + +/** + * Destroys this buffer + */ +Framebuffer.prototype.destroy = function() +{ + var gl = this.gl; + + //TODO + if(this.texture) + { + this.texture.destroy(); + } + + gl.deleteFramebuffer(this.framebuffer); + + this.gl = null; + + this.stencil = null; + this.texture = null; +}; + +/** + * Creates a frame buffer with a texture containing the given data + * @mat can you confirm ? :) + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createRGBA = function(gl, width, height, data) +{ + var texture = Texture.fromData(gl, null, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture); + + fbo.unbind(); + + return fbo; +}; + +/** + * Creates a frame buffer with a texture containing the given data + * @mat not sure what the difference is with the method above ? + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createFloat32 = function(gl, width, height, data) +{ + // create a new texture.. + var texture = new Texture.fromData(gl, data, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture); + + fbo.unbind(); + + return fbo; +}; + +module.exports = Framebuffer; + +},{"./GLTexture":18}],17:[function(require,module,exports){ + +var compileProgram = require('./shader/compileProgram'), + extractAttributes = require('./shader/extractAttributes'), + extractUniforms = require('./shader/extractUniforms'), + generateUniformAccessObject = require('./shader/generateUniformAccessObject'); + +/** + * Helper class to create a webGL Shader + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + */ +var Shader = function(gl, vertexSrc, fragmentSrc) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The shader program + * + * @member {WebGLProgram} + */ + // First compile the program.. + this.program = compileProgram(gl, vertexSrc, fragmentSrc); + + + /** + * The attributes of the shader as an object containing the following properties + * { + * type, + * size, + * location, + * pointer + * } + * @member {Object} + */ + // next extract the attributes + this.attributes = extractAttributes(gl, this.program); + + var uniformData = extractUniforms(gl, this.program); + + /** + * The uniforms of the shader as an object containing the following properties + * { + * gl, + * data + * } + * @member {Object} + */ + this.uniforms = generateUniformAccessObject( gl, uniformData ); +}; +/** + * Uses this shader + */ +Shader.prototype.bind = function() +{ + this.gl.useProgram(this.program); +}; + +/** + * Destroys this shader + * TODO + */ +Shader.prototype.destroy = function() +{ + var gl = this.gl; +}; + +module.exports = Shader; + +},{"./shader/compileProgram":22,"./shader/extractAttributes":24,"./shader/extractUniforms":25,"./shader/generateUniformAccessObject":26}],18:[function(require,module,exports){ + +/** + * Helper class to create a WebGL Texture + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL context + * @param width {number} the width of the texture + * @param height {number} the height of the texture + * @param format {number} the pixel format of the texture. defaults to gl.RGBA + * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE + */ +var Texture = function(gl, width, height, format, type) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + + /** + * The WebGL texture + * + * @member {WebGLTexture} + */ + this.texture = gl.createTexture(); + + /** + * If mipmapping was used for this texture, enable and disable with enableMipmap() + * + * @member {Boolean} + */ + // some settings.. + this.mipmap = false; + + + /** + * Set to true to enable pre-multiplied alpha + * + * @member {Boolean} + */ + this.premultiplyAlpha = false; + + /** + * The width of texture + * + * @member {Number} + */ + this.width = width || 0; + /** + * The height of texture + * + * @member {Number} + */ + this.height = height || 0; + + /** + * The pixel format of the texture. defaults to gl.RGBA + * + * @member {Number} + */ + this.format = format || gl.RGBA; + + /** + * The gl type of the texture. defaults to gl.UNSIGNED_BYTE + * + * @member {Number} + */ + this.type = type || gl.UNSIGNED_BYTE; + + +}; + +/** + * Uploads this texture to the GPU + * @param source {HTMLImageElement|ImageData|HTMLVideoElement} the source image of the texture + */ +Texture.prototype.upload = function(source) +{ + this.bind(); + + var gl = this.gl; + + // if the source is a video, we need to use the videoWidth / videoHeight properties as width / height will be incorrect. + this.width = source.videoWidth || source.width; + this.height = source.videoHeight || source.height; + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); +}; + +var FLOATING_POINT_AVAILABLE = false; + +/** + * Use a data source and uploads this texture to the GPU + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.prototype.uploadData = function(data, width, height) +{ + this.bind(); + + var gl = this.gl; + + this.width = width || this.width; + this.height = height || this.height; + + if(data instanceof Float32Array) + { + if(!FLOATING_POINT_AVAILABLE) + { + var ext = gl.getExtension("OES_texture_float"); + + if(ext) + { + FLOATING_POINT_AVAILABLE = true; + } + else + { + throw new Error('floating point textures not available'); + } + } + + this.type = gl.FLOAT; + } + else + { + // TODO support for other types + this.type = gl.UNSIGNED_BYTE; + } + + + + // what type of data? + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); + +}; + +/** + * Binds the texture + * @param location {@mat} + */ +Texture.prototype.bind = function(location) +{ + var gl = this.gl; + + if(location !== undefined) + { + gl.activeTexture(gl.TEXTURE0 + location); + } + + gl.bindTexture(gl.TEXTURE_2D, this.texture); +}; + +/** + * Unbinds the texture + */ +Texture.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindTexture(gl.TEXTURE_2D, null); +}; + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.minFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + if(this.mipmap) + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); + } + else + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); + } +}; + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.magFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); +}; + +/** + * Enables mipmapping + */ +Texture.prototype.enableMipmap = function() +{ + var gl = this.gl; + + this.bind(); + + this.mipmap = true; + + gl.generateMipmap(gl.TEXTURE_2D); +}; + +/** + * Enables linear filtering + */ +Texture.prototype.enableLinearScaling = function() +{ + this.minFilter(true); + this.magFilter(true); +}; + +/** + * Enables nearest neighbour interpolation + */ +Texture.prototype.enableNearestScaling = function() +{ + this.minFilter(false); + this.magFilter(false); +}; + +/** + * Enables clamping on the texture so WebGL will not repeat it + */ +Texture.prototype.enableWrapClamp = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); +}; + +/** + * Enable tiling on the texture + */ +Texture.prototype.enableWrapRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); +}; + +/** + * @mat + */ +Texture.prototype.enableWrapMirrorRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); +}; + + +/** + * Destroys this texture + */ +Texture.prototype.destroy = function() +{ + var gl = this.gl; + //TODO + gl.deleteTexture(this.texture); +}; + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param source {HTMLImageElement|ImageData} the source image of the texture + * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha + */ +Texture.fromSource = function(gl, source, premultiplyAlpha) +{ + var texture = new Texture(gl); + texture.premultiplyAlpha = premultiplyAlpha || false; + texture.upload(source); + + return texture; +}; + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.fromData = function(gl, data, width, height) +{ + //console.log(data, width, height); + var texture = new Texture(gl); + texture.uploadData(data, width, height); + + return texture; +}; + + +module.exports = Texture; + +},{}],19:[function(require,module,exports){ + +// state object// +var setVertexAttribArrays = require( './setVertexAttribArrays' ); + +/** + * Helper class to work with WebGL VertexArrayObjects (vaos) + * Only works if WebGL extensions are enabled (they usually are) + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + */ +function VertexArrayObject(gl, state) +{ + + this.nativeVaoExtension = ( + gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object') + ); + + this.nativeState = state; + + if(this.nativeVaoExtension) + { + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + + // VAO - overwrite the state.. + this.nativeState = { + tempAttribState: new Array(maxAttribs), + attribState: new Array(maxAttribs) + }; + } + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * An array of attributes ? @mat + * + * @member {Array} + */ + this.attributes = []; + + /** + * @mat + * + * @member {Array} + */ + this.indexBuffer = null; + + /** + * A boolean flag + * + * @member {Boolean} + */ + this.dirty = false; +} + +VertexArrayObject.prototype.constructor = VertexArrayObject; +module.exports = VertexArrayObject; + + +/** + * Binds the buffer + */ +VertexArrayObject.prototype.bind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + + if(this.dirty) + { + this.dirty = false; + this.activate(); + } + } + else + { + + this.activate(); + } + + return this; +}; + +/** + * Unbinds the buffer + */ +VertexArrayObject.prototype.unbind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + return this; +}; + +/** + * Uses this vao + */ +VertexArrayObject.prototype.activate = function() +{ + + var gl = this.gl; + var lastBuffer = null; + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + + if(lastBuffer !== attrib.buffer) + { + attrib.buffer.bind(); + lastBuffer = attrib.buffer; + } + + //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.start || 0); + + + } + + setVertexAttribArrays(gl, this.attributes, this.nativeState); + + this.indexBuffer.bind(); + + return this; +}; + +/** + * + * @param buffer {WebGLBuffer} + * @param attribute {[type]} + * @param type {[type]} + * @param normalized {[type]} + * @param stride {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) +{ + this.attributes.push({ + buffer: buffer, + attribute: attribute, + + location: attribute.location, + type: type || this.gl.FLOAT, + normalized: normalized || false, + stride: stride || 0, + start: start || 0 + }); + + this.dirty = true; + + return this; +}; + +/** + * + * @param buffer {WebGLBuffer} + * @param options {Object} + */ +VertexArrayObject.prototype.addIndex = function(buffer, options) +{ + this.indexBuffer = buffer; + + this.dirty = true; + + return this; +}; + +/** + * Unbinds this vao and disables it + */ +VertexArrayObject.prototype.clear = function() +{ + var gl = this.gl; + + // TODO - should this function unbind after clear? + // for now, no but lets see what happens in the real world! + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + } + + this.attributes.length = 0; + this.indexBuffer = null; + + return this; +}; + +/** + * @mat + * @param type {Number} + * @param size {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.draw = function(type, size, start) +{ + var gl = this.gl; + gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); + + return this; +}; + +/** + * Destroy this vao + */ +VertexArrayObject.prototype.destroy = function() +{ + // lose references + this.gl = null; + this.indexBuffer = null; + this.attributes = null; + this.nativeState = null; + + if(this.nativeVao) + { + this.nativeVaoExtension.deleteVertexArrayOES(this.nativeVao); + } + + this.nativeVaoExtension = null; + this.nativeVao = null; +}; + +},{"./setVertexAttribArrays":21}],20:[function(require,module,exports){ + +/** + * Helper class to create a webGL Context + * + * @class + * @memberof pixi.gl + * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from + * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, + * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available + * @return {WebGLRenderingContext} the WebGL context + */ +var createContext = function(canvas, options) +{ + var gl = canvas.getContext('webgl', options) || + canvas.getContext('experimental-webgl', options); + + if (!gl) + { + // fail, not able to get a context + throw new Error('This browser does not support webGL. Try using the canvas renderer'); + } + + return gl; +}; + +module.exports = createContext; + +},{}],21:[function(require,module,exports){ +var GL_MAP = {}; + +/** + * @mat + * @param gl {WebGLRenderingContext} The current WebGL context + * @param attribs {[type]} + */ +var setVertexAttribArrays = function (gl, attribs, state) +{ + var i; + if(state) + { + var tempAttribState = state.tempAttribState, + attribState = state.attribState; + + for (i = 0; i < tempAttribState.length; i++) + { + tempAttribState[i] = false; + } + + // set the new attribs + for (i = 0; i < attribs.length; i++) + { + tempAttribState[attribs[i].attribute.location] = true; + } + + for (i = 0; i < attribState.length; i++) + { + if (attribState[i] !== tempAttribState[i]) + { + attribState[i] = tempAttribState[i]; + + if (state.attribState[i]) + { + gl.enableVertexAttribArray(i); + } + else + { + gl.disableVertexAttribArray(i); + } + } + } + + } + else + { + for (i = 0; i < attribs.length; i++) + { + var attrib = attribs[i]; + gl.enableVertexAttribArray(attrib.attribute.location); + } + } +}; + +module.exports = setVertexAttribArrays; + +},{}],22:[function(require,module,exports){ + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + * @return {WebGLProgram} the shader program + */ +var compileProgram = function(gl, vertexSrc, fragmentSrc) +{ + var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); + var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); + + var program = gl.createProgram(); + + gl.attachShader(program, glVertShader); + gl.attachShader(program, glFragShader); + gl.linkProgram(program); + + // if linking fails, then log and cleanup + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) + { + console.error('Pixi.js Error: Could not initialize shader.'); + console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); + console.error('gl.getError()', gl.getError()); + + // if there is a program info log, log it + if (gl.getProgramInfoLog(program) !== '') + { + console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); + } + + gl.deleteProgram(program); + program = null; + } + + // clean up some shaders + gl.deleteShader(glVertShader); + gl.deleteShader(glFragShader); + + return program; +}; + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @return {WebGLShader} the shader + */ +var compileShader = function (gl, type, src) +{ + var shader = gl.createShader(type); + + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) + { + console.log(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +}; + +module.exports = compileProgram; + +},{}],23:[function(require,module,exports){ + + +var defaultValue = function(type, size) +{ + switch (type) + { + case 'float': + return 0; + + case 'vec2': + return new Float32Array(2 * size); + + case 'vec3': + return new Float32Array(3 * size); + + case 'vec4': + return new Float32Array(4 * size); + + case 'int': + case 'sampler2D': + return 0; + + case 'ivec2': + return new Int32Array(2 * size); + + case 'ivec3': + return new Int32Array(3 * size); + + case 'ivec4': + return new Int32Array(4 * size); + + case 'bool': + return false; + + case 'bvec2': + + return booleanArray( 2 * size); + + case 'bvec3': + return booleanArray(3 * size); + + case 'bvec4': + return booleanArray(4 * size); + + case 'mat2': + return new Float32Array([1, 0, + 0, 1]); + + case 'mat3': + return new Float32Array([1, 0, 0, + 0, 1, 0, + 0, 0, 1]); + + case 'mat4': + return new Float32Array([1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]); + } +}; + +var booleanArray = function(size) +{ + var array = new Array(size); + + for (var i = 0; i < array.length; i++) + { + array[i] = false; + } + + return array; +}; + +module.exports = defaultValue; + +},{}],24:[function(require,module,exports){ + +var mapType = require('./mapType'); +var mapSize = require('./mapSize'); + +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the attributes from + * @return attributes {Object} + */ +var extractAttributes = function(gl, program) +{ + var attributes = {}; + + var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES); + + for (var i = 0; i < totalAttributes; i++) + { + var attribData = gl.getActiveAttrib(program, i); + var type = mapType(gl, attribData.type); + + attributes[attribData.name] = { + type:type, + size:mapSize(type), + location:gl.getAttribLocation(program, attribData.name), + //TODO - make an attribute object + pointer: pointer + }; + } + + return attributes; +}; + +var pointer = function(type, normalized, stride, start){ + // console.log(this.location) + gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); +}; + +module.exports = extractAttributes; + +},{"./mapSize":27,"./mapType":28}],25:[function(require,module,exports){ +var mapType = require('./mapType'); +var defaultValue = require('./defaultValue'); + +/** + * Extracts the uniforms + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the uniforms from + * @return uniforms {Object} + */ +var extractUniforms = function(gl, program) +{ + var uniforms = {}; + + var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + + for (var i = 0; i < totalUniforms; i++) + { + var uniformData = gl.getActiveUniform(program, i); + var name = uniformData.name.replace(/\[.*?\]/, ""); + var type = mapType(gl, uniformData.type ); + + uniforms[name] = { + type:type, + size:uniformData.size, + location:gl.getUniformLocation(program, name), + value:defaultValue(type, uniformData.size) + }; + } + + return uniforms; +}; + +module.exports = extractUniforms; + +},{"./defaultValue":23,"./mapType":28}],26:[function(require,module,exports){ +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param uniforms {Array} @mat ? + * @return attributes {Object} + */ +var generateUniformAccessObject = function(gl, uniformData) +{ + // this is the object we will be sending back. + // an object hierachy will be created for structs + var uniforms = {data:{}}; + + uniforms.gl = gl; + + var uniformKeys= Object.keys(uniformData); + + for (var i = 0; i < uniformKeys.length; i++) + { + var fullName = uniformKeys[i]; + + var nameTokens = fullName.split('.'); + var name = nameTokens[nameTokens.length - 1]; + + var uniformGroup = getUniformGroup(nameTokens, uniforms); + + var uniform = uniformData[fullName]; + uniformGroup.data[name] = uniform; + + uniformGroup.gl = gl; + + Object.defineProperty(uniformGroup, name, { + get: generateGetter(name), + set: generateSetter(name, uniform) + }); + } + + return uniforms; +}; + +var generateGetter = function(name) +{ + var template = getterTemplate.replace('%%', name); + return new Function(template); // jshint ignore:line +}; + +var generateSetter = function(name, uniform) +{ + var template = setterTemplate.replace(/%%/g, name); + var setTemplate; + + if(uniform.size === 1) + { + setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; + } + else + { + setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; + } + + if(setTemplate) + { + template += "\nthis.gl." + setTemplate + ";"; + } + + return new Function('value', template); // jshint ignore:line +}; + +var getUniformGroup = function(nameTokens, uniform) +{ + var cur = uniform; + + for (var i = 0; i < nameTokens.length - 1; i++) + { + var o = cur[nameTokens[i]] || {data:{}}; + cur[nameTokens[i]] = o; + cur = o; + } + + return cur; +}; + +var getterTemplate = [ + 'return this.data.%%.value;', +].join('\n'); + +var setterTemplate = [ + 'this.data.%%.value = value;', + 'var location = this.data.%%.location;' +].join('\n'); + + +var GLSL_TO_SINGLE_SETTERS = { + + 'float': 'uniform1f(location, value)', + + 'vec2': 'uniform2f(location, value[0], value[1])', + 'vec3': 'uniform3f(location, value[0], value[1], value[2])', + 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', + + 'int': 'uniform1i(location, value)', + 'ivec2': 'uniform2i(location, value[0], value[1])', + 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', + 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'bool': 'uniform1i(location, value)', + 'bvec2': 'uniform2i(location, value[0], value[1])', + 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', + 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'mat2': 'uniformMatrix2fv(location, false, value)', + 'mat3': 'uniformMatrix3fv(location, false, value)', + 'mat4': 'uniformMatrix4fv(location, false, value)', + + 'sampler2D':'uniform1i(location, value)' +}; + +var GLSL_TO_ARRAY_SETTERS = { + + 'float': 'uniform1fv(location, value)', + + 'vec2': 'uniform2fv(location, value)', + 'vec3': 'uniform3fv(location, value)', + 'vec4': 'uniform4fv(location, value)', + + 'int': 'uniform1iv(location, value)', + 'ivec2': 'uniform2iv(location, value)', + 'ivec3': 'uniform3iv(location, value)', + 'ivec4': 'uniform4iv(location, value)', + + 'bool': 'uniform1iv(location, value)', + 'bvec2': 'uniform2iv(location, value)', + 'bvec3': 'uniform3iv(location, value)', + 'bvec4': 'uniform4iv(location, value)', + + 'sampler2D':'uniform1iv(location, value)' +}; + +module.exports = generateUniformAccessObject; + +},{}],27:[function(require,module,exports){ + + +var mapSize = function(type) +{ + return GLSL_TO_SIZE[type]; +}; + + +var GLSL_TO_SIZE = { + 'float': 1, + 'vec2': 2, + 'vec3': 3, + 'vec4': 4, + + 'int': 1, + 'ivec2': 2, + 'ivec3': 3, + 'ivec4': 4, + + 'bool': 1, + 'bvec2': 2, + 'bvec3': 3, + 'bvec4': 4, + + 'mat2': 4, + 'mat3': 9, + 'mat4': 16, + + 'sampler2D': 1 +}; + +module.exports = mapSize; + +},{}],28:[function(require,module,exports){ + + +var mapSize = function(gl, type) +{ + if(!GL_TABLE) + { + var typeNames = Object.keys(GL_TO_GLSL_TYPES); + + GL_TABLE = {}; + + for(var i = 0; i < typeNames.length; ++i) + { + var tn = typeNames[i]; + GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; + } + } + + return GL_TABLE[type]; +}; + +var GL_TABLE = null; + +var GL_TO_GLSL_TYPES = { + 'FLOAT': 'float', + 'FLOAT_VEC2': 'vec2', + 'FLOAT_VEC3': 'vec3', + 'FLOAT_VEC4': 'vec4', + + 'INT': 'int', + 'INT_VEC2': 'ivec2', + 'INT_VEC3': 'ivec3', + 'INT_VEC4': 'ivec4', + + 'BOOL': 'bool', + 'BOOL_VEC2': 'bvec2', + 'BOOL_VEC3': 'bvec3', + 'BOOL_VEC4': 'bvec4', + + 'FLOAT_MAT2': 'mat2', + 'FLOAT_MAT3': 'mat3', + 'FLOAT_MAT4': 'mat4', + + 'SAMPLER_2D': 'sampler2D' +}; + +module.exports = mapSize; + },{}],29:[function(require,module,exports){ (function (process){ /*! @@ -6991,7 +7035,7 @@ }()); }).call(this,require('_process')) -},{"_process":19}],30:[function(require,module,exports){ +},{"_process":4}],30:[function(require,module,exports){ var async = require('async'), urlParser = require('url'), Resource = require('./Resource'), @@ -7449,7 +7493,7 @@ Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; -},{"./Resource":31,"async":29,"eventemitter3":26,"url":24}],31:[function(require,module,exports){ +},{"./Resource":31,"async":29,"eventemitter3":11,"url":9}],31:[function(require,module,exports){ var EventEmitter = require('eventemitter3'), _url = require('url'), // tests is CORS is supported in XHR, if not we need to use XDR @@ -8251,7 +8295,7 @@ map[extname] = val; } -},{"eventemitter3":26,"url":24}],32:[function(require,module,exports){ +},{"eventemitter3":11,"url":9}],32:[function(require,module,exports){ module.exports = { // private property @@ -8943,7 +8987,7 @@ Shader.prototype.constructor = Shader; module.exports = Shader; -},{"./const":40,"pixi-gl-core":1}],40:[function(require,module,exports){ +},{"./const":40,"pixi-gl-core":14}],40:[function(require,module,exports){ /** * Constant values used in pixi @@ -10397,7 +10441,7 @@ this.filterArea = null; }; -},{"../math":62,"./Transform":44,"eventemitter3":26}],43:[function(require,module,exports){ +},{"../math":62,"./Transform":44,"eventemitter3":11}],43:[function(require,module,exports){ /** * An observable point is a point that triggers a callback when the point's position is changed. * @@ -12609,7 +12653,7 @@ this.glIndices = null; }; -},{"pixi-gl-core":1}],52:[function(require,module,exports){ +},{"pixi-gl-core":14}],52:[function(require,module,exports){ var Shader = require('../../../Shader'); /** @@ -13047,7 +13091,7 @@ module.exports = buildPoly; -},{"../../../utils":110,"./buildLine":54,"earcut":25}],56:[function(require,module,exports){ +},{"../../../utils":110,"./buildLine":54,"earcut":10}],56:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -13249,7 +13293,7 @@ module.exports = buildRoundedRectangle; -},{"../../../utils":110,"./buildLine":54,"earcut":25}],58:[function(require,module,exports){ +},{"../../../utils":110,"./buildLine":54,"earcut":10}],58:[function(require,module,exports){ /** * @file Main export of the PIXI core library * @author Mat Groves @@ -13346,7 +13390,7 @@ } }); -},{"./Shader":39,"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./display/Transform":44,"./display/TransformStatic":45,"./graphics/Graphics":46,"./graphics/GraphicsData":47,"./graphics/canvas/CanvasGraphicsRenderer":48,"./graphics/webgl/GraphicsRenderer":50,"./math":62,"./renderers/canvas/CanvasRenderer":69,"./renderers/canvas/utils/CanvasRenderTarget":71,"./renderers/webgl/WebGLRenderer":76,"./renderers/webgl/filters/Filter":78,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":81,"./renderers/webgl/managers/WebGLManager":85,"./renderers/webgl/utils/ObjectRenderer":86,"./renderers/webgl/utils/Quad":87,"./renderers/webgl/utils/RenderTarget":88,"./sprites/Sprite":92,"./sprites/canvas/CanvasSpriteRenderer":93,"./sprites/canvas/CanvasTinter":94,"./sprites/webgl/SpriteRenderer":96,"./text/Text":98,"./text/TextStyle":99,"./textures/BaseRenderTexture":100,"./textures/BaseTexture":101,"./textures/RenderTexture":102,"./textures/Texture":103,"./textures/TextureUvs":104,"./textures/VideoBaseTexture":105,"./ticker":107,"./utils":110,"pixi-gl-core":1}],59:[function(require,module,exports){ +},{"./Shader":39,"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./display/Transform":44,"./display/TransformStatic":45,"./graphics/Graphics":46,"./graphics/GraphicsData":47,"./graphics/canvas/CanvasGraphicsRenderer":48,"./graphics/webgl/GraphicsRenderer":50,"./math":62,"./renderers/canvas/CanvasRenderer":69,"./renderers/canvas/utils/CanvasRenderTarget":71,"./renderers/webgl/WebGLRenderer":76,"./renderers/webgl/filters/Filter":78,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":81,"./renderers/webgl/managers/WebGLManager":85,"./renderers/webgl/utils/ObjectRenderer":86,"./renderers/webgl/utils/Quad":87,"./renderers/webgl/utils/RenderTarget":88,"./sprites/Sprite":92,"./sprites/canvas/CanvasSpriteRenderer":93,"./sprites/canvas/CanvasTinter":94,"./sprites/webgl/SpriteRenderer":96,"./text/Text":98,"./text/TextStyle":99,"./textures/BaseRenderTexture":100,"./textures/BaseTexture":101,"./textures/RenderTexture":102,"./textures/Texture":103,"./textures/TextureUvs":104,"./textures/VideoBaseTexture":105,"./ticker":107,"./utils":110,"pixi-gl-core":14}],59:[function(require,module,exports){ // Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16 var ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1]; @@ -14896,7 +14940,7 @@ this._lastObjectRendered = null; }; -},{"../const":40,"../display/Container":41,"../math":62,"../textures/RenderTexture":102,"../utils":110,"eventemitter3":26}],69:[function(require,module,exports){ +},{"../const":40,"../display/Container":41,"../math":62,"../textures/RenderTexture":102,"../utils":110,"eventemitter3":11}],69:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), CanvasMaskManager = require('./utils/CanvasMaskManager'), CanvasRenderTarget = require('./utils/CanvasRenderTarget'), @@ -15841,7 +15885,7 @@ module.exports = TextureManager; -},{"../../const":40,"../../utils":110,"./utils/RenderTarget":88,"pixi-gl-core":1}],76:[function(require,module,exports){ +},{"../../const":40,"../../utils":110,"./utils/RenderTarget":88,"pixi-gl-core":14}],76:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), @@ -16399,7 +16443,7 @@ // this = null; }; -},{"../../const":40,"../../utils":110,"../SystemRenderer":68,"./TextureGarbageCollector":74,"./TextureManager":75,"./WebGLState":77,"./managers/FilterManager":82,"./managers/MaskManager":83,"./managers/StencilManager":84,"./utils/ObjectRenderer":86,"./utils/RenderTarget":88,"./utils/mapWebGLDrawModesToPixi":91,"pixi-gl-core":1}],77:[function(require,module,exports){ +},{"../../const":40,"../../utils":110,"../SystemRenderer":68,"./TextureGarbageCollector":74,"./TextureManager":75,"./WebGLState":77,"./managers/FilterManager":82,"./managers/MaskManager":83,"./managers/StencilManager":84,"./utils/ObjectRenderer":86,"./utils/RenderTarget":88,"./utils/mapWebGLDrawModesToPixi":91,"pixi-gl-core":14}],77:[function(require,module,exports){ var mapWebGLBlendModesToPixi = require('./utils/mapWebGLBlendModesToPixi'); /** @@ -16868,7 +16912,7 @@ module.exports = extractUniformsFromSrc; -},{"pixi-gl-core/lib/shader/defaultValue":10,"pixi-gl-core/lib/shader/mapSize":14}],80:[function(require,module,exports){ +},{"pixi-gl-core/lib/shader/defaultValue":23,"pixi-gl-core/lib/shader/mapSize":27}],80:[function(require,module,exports){ var math = require('../../../math'); /* @@ -17048,7 +17092,6 @@ this.resolution = 1; }; -FilterManager.pool = {}; /** * @class @@ -17074,6 +17117,7 @@ this.shaderCache = {}; // todo add default! + this.pool = {}; } FilterManager.prototype = Object.create(WebGLManager.prototype); @@ -17109,7 +17153,7 @@ destinationFrame.width = sourceFrame.width; destinationFrame.height = sourceFrame.height; - var renderTarget = FilterManager.getPotRenderTarget(renderer.gl, sourceFrame.width, sourceFrame.height, resolution); + var renderTarget = this.getPotRenderTarget(renderer.gl, sourceFrame.width, sourceFrame.height, resolution); currentState.target = target; currentState.filters = filters; @@ -17137,13 +17181,13 @@ if(filters.length === 1) { - filters[0].apply(this, currentState.renderTarget, lastState.renderTarget, true); - FilterManager.freePotRenderTarget(currentState.renderTarget); + filters[0].apply(this, currentState.renderTarget, lastState.renderTarget, false); + this.freePotRenderTarget(currentState.renderTarget); } else { var flip = currentState.renderTarget; - var flop = FilterManager.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); + var flop = this.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, 1); flop.setFrame(currentState.destinationFrame, currentState.sourceFrame); for (var i = 0; i < filters.length-1; i++) @@ -17155,10 +17199,10 @@ flop = t; } - filters[i].apply(this, flip, lastState.renderTarget, true); + filters[i].apply(this, flip, lastState.renderTarget, false); - FilterManager.freePotRenderTarget(flip); - FilterManager.freePotRenderTarget(flop); + this.freePotRenderTarget(flip); + this.freePotRenderTarget(flop); } this.stackIndex--; @@ -17300,7 +17344,7 @@ FilterManager.prototype.getRenderTarget = function() { var currentState = this.stack[this.stackIndex]; - var renderTarget = FilterManager.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); + var renderTarget = this.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); return renderTarget; @@ -17308,7 +17352,7 @@ FilterManager.prototype.returnRenderTarget = function(renderTarget) { - return FilterManager.freePotRenderTarget(renderTarget); + return this.freePotRenderTarget(renderTarget); }; /* @@ -17344,14 +17388,14 @@ FilterManager.prototype.destroy = function() { this.shaderCache = []; - FilterManager.emptyPool(); + this.emptyPool(); }; //TODO move to a seperate class could be on renderer? //also - could cause issue with multiple contexts? -FilterManager.getPotRenderTarget = function(gl, minWidth, minHeight, resolution) +FilterManager.prototype.getPotRenderTarget = function(gl, minWidth, minHeight, resolution) { //TODO you coud return a bigger texture if there is not one in the pool? minWidth = bitTwiddle.nextPow2(minWidth * resolution); @@ -17360,11 +17404,11 @@ var key = ((minWidth & 0xFFFF) << 16) | ( minHeight & 0xFFFF); // console.log(minWidth + " " + minHeight) - if(!FilterManager.pool[key]) { - FilterManager.pool[key] = []; + if(!this.pool[key]) { + this.pool[key] = []; } - var renderTarget = FilterManager.pool[key].pop() || new RenderTarget(gl, minWidth, minHeight, null, 1); + var renderTarget = this.pool[key].pop() || new RenderTarget(gl, minWidth, minHeight, null, 1); //manually tweak the resolution... //this will not modify the size of the frame buffer, just its resolution. @@ -17375,11 +17419,11 @@ return renderTarget; }; -FilterManager.emptyPool = function() +FilterManager.prototype.emptyPool = function() { - for (var i in FilterManager.pool) + for (var i in this.pool) { - var textures = FilterManager.pool[i]; + var textures = this.pool[i]; if(textures) { for (var j = 0; j < textures.length; j++) @@ -17389,19 +17433,19 @@ } } - FilterManager.pool = {}; + this.pool = {}; }; -FilterManager.freePotRenderTarget = function(renderTarget) +FilterManager.prototype.freePotRenderTarget = function(renderTarget) { var minWidth = renderTarget.size.width * renderTarget.resolution; var minHeight = renderTarget.size.height * renderTarget.resolution; var key = ((minWidth & 0xFFFF) << 16) | (minHeight & 0xFFFF); - FilterManager.pool[key].push(renderTarget); + this.pool[key].push(renderTarget); }; -},{"../../../Shader":39,"../../../math":62,"../filters/filterTransforms":80,"../utils/Quad":87,"../utils/RenderTarget":88,"./WebGLManager":85,"bit-twiddle":17}],83:[function(require,module,exports){ +},{"../../../Shader":39,"../../../math":62,"../filters/filterTransforms":80,"../utils/Quad":87,"../utils/RenderTarget":88,"./WebGLManager":85,"bit-twiddle":2}],83:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), AlphaMaskFilter = require('../filters/spriteMask/SpriteMaskFilter'); @@ -17564,10 +17608,11 @@ this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST); - this.renderer.gl.scissor(bounds.x, - renderTarget.root ? renderTarget.size.height - bounds.y - bounds.height : bounds.y, - bounds.width , - bounds.height); + var resolution = this.renderer.resolution; + this.renderer.gl.scissor(bounds.x * resolution, + (renderTarget.root ? renderTarget.size.height - bounds.y - bounds.height : bounds.y) * resolution, + bounds.width * resolution, + bounds.height * resolution); this.scissorRenderTarget = renderTarget; this.scissorData = maskData; @@ -17970,7 +18015,7 @@ module.exports = Quad; -},{"../../../utils/createIndicesForQuads":108,"pixi-gl-core":1}],88:[function(require,module,exports){ +},{"../../../utils/createIndicesForQuads":108,"pixi-gl-core":14}],88:[function(require,module,exports){ var math = require('../../../math'), CONST = require('../../../const'), GLFramebuffer = require('pixi-gl-core').GLFramebuffer; @@ -18296,7 +18341,7 @@ this.texture = null; }; -},{"../../../const":40,"../../../math":62,"pixi-gl-core":1}],89:[function(require,module,exports){ +},{"../../../const":40,"../../../math":62,"pixi-gl-core":14}],89:[function(require,module,exports){ var glCore = require('pixi-gl-core'); var fragTemplate = [ @@ -18377,7 +18422,7 @@ module.exports = checkMaxIfStatmentsInShader; -},{"pixi-gl-core":1}],90:[function(require,module,exports){ +},{"pixi-gl-core":14}],90:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -18971,7 +19016,7 @@ width = texture._frame.width, height = texture._frame.height; - if (texture.orig.width <= 0 || texture.orig.height <= 0) + if (texture.orig.width <= 0 || texture.orig.height <= 0 || !texture.baseTexture.source) { return; } @@ -19750,7 +19795,7 @@ }; -},{"../../const":40,"../../renderers/webgl/WebGLRenderer":76,"../../renderers/webgl/utils/ObjectRenderer":86,"../../renderers/webgl/utils/checkMaxIfStatmentsInShader":89,"../../utils/createIndicesForQuads":108,"./BatchBuffer":95,"./generateMultiTextureShader":97,"bit-twiddle":17,"pixi-gl-core":1}],97:[function(require,module,exports){ +},{"../../const":40,"../../renderers/webgl/WebGLRenderer":76,"../../renderers/webgl/utils/ObjectRenderer":86,"../../renderers/webgl/utils/checkMaxIfStatmentsInShader":89,"../../utils/createIndicesForQuads":108,"./BatchBuffer":95,"./generateMultiTextureShader":97,"bit-twiddle":2,"pixi-gl-core":14}],97:[function(require,module,exports){ var Shader = require('../../Shader'); @@ -19891,6 +19936,14 @@ */ this._styleListener = null; + /** + * Private tracker for the current font. + * + * @member {string} + * @private + */ + this._font = ''; + var texture = Texture.fromCanvas(this.canvas); texture.trim = new math.Rectangle(); Sprite.call(this, texture); @@ -20022,7 +20075,12 @@ return; } var style = this._style; - this.context.font = style.font; + + // build canvas api font setting from invididual components. Convert a numeric style.fontSize to px + var fontSizeString = (typeof style.fontSize === 'number') ? style.fontSize + 'px' : style.fontSize; + this._font = style.fontStyle + ' ' + style.fontVariant + ' ' + style.fontWeight + ' ' + fontSizeString + ' ' + style.fontFamily; + + this.context.font = this._font; // word wrap // preserve original text @@ -20034,7 +20092,7 @@ // calculate text width var lineWidths = new Array(lines.length); var maxLineWidth = 0; - var fontProperties = this.determineFontProperties(style.font); + var fontProperties = this.determineFontProperties(this._font); var i; for (i = 0; i < lines.length; i++) @@ -20074,7 +20132,7 @@ //this.context.fillStyle="#FF0000"; //this.context.fillRect(0, 0, this.canvas.width, this.canvas.height); - this.context.font = style.font; + this.context.font = this._font; this.context.strokeStyle = style.stroke; this.context.lineWidth = style.strokeThickness; this.context.textBaseline = style.textBaseline; @@ -20488,7 +20546,11 @@ * @param [style.dropShadowDistance=5] {number} Set a distance of the drop shadow * @param [style.fill='black'] {string|number|CanvasGradient|CanvasPattern} A canvas fillstyle that will be used on the * text e.g 'red', '#00FF00'. @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN} - * @param [style.font='bold 20pt Arial'] {string} The style and size of the font + * @param [style.fontFamily='Arial'] {string} The font family + * @param [style.fontSize=26] {number|string} The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') + * @param [style.fontStyle='normal'] {string} The font style ('normal', 'italic' or 'oblique') + * @param [style.fontVariant='normal'] {string} The font variant ('normal' or 'small-caps') + * @param [style.fontWeight='normal'] {string} The font weight ('normal', 'bold', 'bolder', 'lighter' and '100', '200', '300', '400', '500', '600', '700', 800' or '900') * @param [style.letterSpacing=0] {number} The amount of spacing between letters, default is 0 * @param [style.lineHeight] {number} The line height, a number that represents the vertical space that a letter uses * @param [style.lineJoin='miter'] {string} The lineJoin property sets the type of corner created, it can resolve @@ -20523,7 +20585,11 @@ dropShadowColor: '#000000', dropShadowDistance: 5, fill: 'black', - font: 'bold 20pt Arial', + fontFamily: 'Arial', + fontSize: 26, + fontStyle: 'normal', + fontVariant: 'normal', + fontWeight: 'normal', letterSpacing: 0, lineHeight: 0, lineJoin: 'miter', @@ -20687,16 +20753,76 @@ } }, - font: { + fontFamily: { get: function () { - return this._font; + return this._fontFamily; }, - set: function (font) + set: function (fontFamily) { - if (this._font !== font) + if (this.fontFamily !== fontFamily) { - this._font = font; + this._fontFamily = fontFamily; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontSize: { + get: function () + { + return this._fontSize; + }, + set: function (fontSize) + { + if (this._fontSize !== fontSize) + { + this._fontSize = fontSize; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontStyle: { + get: function () + { + return this._fontStyle; + }, + set: function (fontStyle) + { + if (this._fontStyle !== fontStyle) + { + this._fontStyle = fontStyle; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontVariant: { + get: function () + { + return this._fontVariant; + }, + set: function (fontVariant) + { + if (this._fontVariant !== fontVariant) + { + this._fontVariant = fontVariant; + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } + }, + + fontWeight: { + get: function () + { + return this._fontWeight; + }, + set: function (fontWeight) + { + if (this._fontWeight !== fontWeight) + { + this._fontWeight = fontWeight; this.emit(CONST.TEXT_STYLE_CHANGED); } } @@ -20870,7 +20996,7 @@ } } -},{"../const":40,"../utils":110,"eventemitter3":26}],100:[function(require,module,exports){ +},{"../const":40,"../utils":110,"eventemitter3":11}],100:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), CONST = require('../const'); @@ -21455,7 +21581,7 @@ return baseTexture; }; -},{"../const":40,"../utils":110,"../utils/determineCrossOrigin":109,"bit-twiddle":17,"eventemitter3":26}],102:[function(require,module,exports){ +},{"../const":40,"../utils":110,"../utils/determineCrossOrigin":109,"bit-twiddle":2,"eventemitter3":11}],102:[function(require,module,exports){ var BaseRenderTexture = require('./BaseRenderTexture'), Texture = require('./Texture'); @@ -22078,7 +22204,7 @@ Texture.EMPTY.emit = function() {}; -},{"../math":62,"../utils":110,"./BaseTexture":101,"./TextureUvs":104,"./VideoBaseTexture":105,"eventemitter3":26}],104:[function(require,module,exports){ +},{"../math":62,"../utils":110,"./BaseTexture":101,"./TextureUvs":104,"./VideoBaseTexture":105,"eventemitter3":11}],104:[function(require,module,exports){ /** * A standard object to store the Uvs of a texture @@ -22753,7 +22879,7 @@ module.exports = Ticker; -},{"../const":40,"eventemitter3":26}],107:[function(require,module,exports){ +},{"../const":40,"eventemitter3":11}],107:[function(require,module,exports){ var Ticker = require('./Ticker'); /** @@ -22885,7 +23011,7 @@ module.exports = determineCrossOrigin; -},{"url":24}],110:[function(require,module,exports){ +},{"url":9}],110:[function(require,module,exports){ var CONST = require('../const'); /** @@ -23095,7 +23221,7 @@ BaseTextureCache: {} }; -},{"../const":40,"./pluginTarget":112,"eventemitter3":26}],111:[function(require,module,exports){ +},{"../const":40,"./pluginTarget":112,"eventemitter3":11}],111:[function(require,module,exports){ var Device = require('ismobilejs'); @@ -23116,7 +23242,7 @@ }; module.exports = maxRecommendedTextures; -},{"ismobilejs":27}],112:[function(require,module,exports){ +},{"ismobilejs":12}],112:[function(require,module,exports){ /** * Mixins functionality to make an object have "plugins". * @@ -23192,7 +23318,8 @@ mesh = require('./mesh'), particles = require('./particles'), extras = require('./extras'), - filters = require('./filters'); + filters = require('./filters'), + CONST = require('./core/const'); // provide method to give a stack track for warnings // useful for tracking-down where deprecated methods/properties/classes @@ -23569,6 +23696,90 @@ warn('setStyle is now deprecated, please use the style property, e.g : myText.style = style;'); }; +Object.defineProperties(core.TextStyle.prototype, { + font: { + get: function () + { + warn('text style property \'font\' is now deprecated, please use the \'fontFamily\',\'fontSize\',fontStyle\',\'fontVariant\' and \'fontWeight\' properties from now on'); + var fontSizeString = (typeof this._fontSize === 'number') ? this._fontSize + 'px' : this._fontSize; + return this._fontStyle + ' ' + this._fontVariant + ' ' + this._fontWeight + ' ' + fontSizeString + ' ' + this._fontFamily; + }, + set: function (font) + { + warn('text style property \'font\' is now deprecated, please use the \'fontFamily\',\'fontSize\',fontStyle\',\'fontVariant\' and \'fontWeight\' properties from now on'); + + // can work out fontStyle from search of whole string + if ( font.indexOf('italic') > 1 ) + { + this._fontStyle = 'italic'; + } + else if ( font.indexOf('oblique') > -1 ) + { + this._fontStyle = 'oblique'; + } + else + { + this._fontStyle = 'normal'; + } + + // can work out fontVariant from search of whole string + if ( font.indexOf('small-caps') > -1 ) + { + this._fontVariant = 'small-caps'; + } + else + { + this._fontVariant = 'normal'; + } + + // fontWeight and fontFamily are tricker to find, but it's easier to find the fontSize due to it's units + var splits = font.split(' '); + var i; + var fontSizeIndex = -1; + + this._fontSize = 26; + for ( i = 0; i < splits.length; ++i ) + { + if ( splits[i].match( /(px|pt|em|%)/ ) ) + { + fontSizeIndex = i; + this._fontSize = splits[i]; + break; + } + } + + // we can now search for fontWeight as we know it must occur before the fontSize + this._fontWeight = 'normal'; + for ( i = 0; i < fontSizeIndex; ++i ) + { + if ( splits[i].match( /(bold|bolder|lighter|100|200|300|400|500|600|700|800|900)/ ) ) + { + this._fontWeight = splits[i]; + break; + } + } + + // and finally join everything together after the fontSize in case the font family has multiple words + if ( fontSizeIndex > -1 && fontSizeIndex < splits.length-1 ) + { + this._fontFamily = ''; + for ( i = fontSizeIndex + 1; i < splits.length; ++i ) + { + this._fontFamily += splits[i] + ' '; + } + + this._fontFamily = this._fontFamily.slice(0, -1); + } + else + { + this._fontFamily = 'Arial'; + } + + this.emit(CONST.TEXT_STYLE_CHANGED); + } + } +} ); + /** * @method * @name PIXI.Texture#setFrame @@ -23647,7 +23858,7 @@ }; -},{"./core":58,"./extras":123,"./filters":135,"./mesh":150,"./particles":153}],114:[function(require,module,exports){ +},{"./core":58,"./core/const":40,"./extras":123,"./filters":135,"./mesh":150,"./particles":153}],114:[function(require,module,exports){ var core = require('../../core'), tempRect = new core.Rectangle(); @@ -28149,7 +28360,7 @@ }; }; -},{"../core":58,"../extras":123,"path":18,"resource-loader":33}],143:[function(require,module,exports){ +},{"../core":58,"../extras":123,"path":3,"resource-loader":33}],143:[function(require,module,exports){ /** * @file Main export of the PIXI loaders library * @author Mat Groves @@ -28349,7 +28560,7 @@ }; }; -},{"../core":58,"async":16,"path":18,"resource-loader":33}],146:[function(require,module,exports){ +},{"../core":58,"async":1,"path":3,"resource-loader":33}],146:[function(require,module,exports){ var core = require('../core'); module.exports = function () @@ -28908,7 +29119,7 @@ TRIANGLES: 1 }; -},{"../core":58,"./webgl/MeshShader":151,"pixi-gl-core":1}],148:[function(require,module,exports){ +},{"../core":58,"./webgl/MeshShader":151,"pixi-gl-core":14}],148:[function(require,module,exports){ var Mesh = require('./Mesh'); /** @@ -29882,7 +30093,7 @@ this.staticBuffer.destroy(); }; -},{"../../core/utils/createIndicesForQuads":108,"pixi-gl-core":1}],155:[function(require,module,exports){ +},{"../../core/utils/createIndicesForQuads":108,"pixi-gl-core":14}],155:[function(require,module,exports){ var core = require('../../core'), ParticleShader = require('./ParticleShader'), ParticleBuffer = require('./ParticleBuffer'); @@ -30406,7 +30617,7 @@ Object.assign = require('object-assign'); } -},{"object-assign":28}],159:[function(require,module,exports){ +},{"object-assign":13}],159:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); diff --git a/bin/pixi.js.map b/bin/pixi.js.map index f2f74f1..b4f59a8 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= data.byteLength)\n\t{\n\t\tgl.bufferSubData(this.type, offset, data);\n\t}\n\telse\n\t{\n\t\tgl.bufferData(this.type, data, this.drawType);\n\t}\n\n\tthis.data = data;\n};\n/**\n * Binds the buffer\n *\n */\nBuffer.prototype.bind = function()\n{\n\tvar gl = this.gl;\n\tgl.bindBuffer(this.type, this.buffer);\n};\n\nBuffer.createVertexBuffer = function(gl, data, drawType)\n{\n\treturn new Buffer(gl, gl.ARRAY_BUFFER, data, drawType);\n};\n\nBuffer.createIndexBuffer = function(gl, data, drawType)\n{\n\treturn new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType);\n};\n\nBuffer.create = function(gl, type, data, drawType)\n{\n\treturn new Buffer(gl, type, drawType);\n};\n\n/**\n * Destroys the buffer\n *\n */\nBuffer.prototype.destroy = function(){\n\tthis.gl.deleteBuffer(this.buffer);\n};\n\nmodule.exports = Buffer;\n\n},{}],3:[function(require,module,exports){\n\nvar Texture = require('./GLTexture');\n\n/**\n * Helper class to create a webGL Framebuffer\n *\n * @class\n * @memberof pixi.gl\n * @param gl {WebGLRenderingContext} The current WebGL rendering context\n * @param width {Number} the width of the drawing area of the frame buffer\n * @param height {Number} the height of the drawing area of the frame buffer\n */\nvar Framebuffer = function(gl, width, height)\n{\n\t/**\n * The current WebGL rendering context\n *\n * @member {WebGLRenderingContext}\n */\n\tthis.gl = gl;\n\n\t/**\n * The frame buffer\n *\n * @member {WebGLFramebuffer}\n */\n\tthis.framebuffer = gl.createFramebuffer();\n\n\t/**\n * The stencil buffer\n *\n * @member {WebGLRenderbuffer}\n */\n\tthis.stencil = null;\n\n\t/**\n * The stencil buffer\n *\n * @member {GLTexture}\n */\n\tthis.texture = null;\n\n\t/**\n * The width of the drawing area of the buffer\n *\n * @member {Number}\n */\n\tthis.width = width || 100;\n\t/**\n * The height of the drawing area of the buffer\n *\n * @member {Number}\n */\n\tthis.height = height || 100;\n};\n\n/**\n * Adds a texture to the frame buffer\n * @param texture {GLTexture}\n */\nFramebuffer.prototype.enableTexture = function(texture)\n{\n\tvar gl = this.gl;\n\n\tthis.texture = texture || new Texture(gl);\n\n\tthis.texture.bind();\n\n\t//gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n\n\tthis.bind();\n\n\tgl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0);\n};\n\n/**\n * Initialises the stencil buffer\n * @mat maybe you can come up with a better explaination\n */\nFramebuffer.prototype.enableStencil = function()\n{\n\tif(this.stencil)return;\n\n\tvar gl = this.gl;\n\n\tthis.stencil = gl.createRenderbuffer();\n\n gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil);\n\n // TODO.. this is depth AND stencil?\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil);\n gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height );\n};\n\n/**\n * Erases the drawing area and fills it with a colour\n * @param r {Number} the red value of the clearing colour\n * @param g {Number} the green value of the clearing colour\n * @param b {Number} the blue value of the clearing colour\n * @param a {Number} the alpha value of the clearing colour\n */\nFramebuffer.prototype.clear = function( r, g, b, a )\n{\n\tthis.bind();\n\n\tvar gl = this.gl;\n\n gl.clearColor(r, g, b, a);\n gl.clear(gl.COLOR_BUFFER_BIT);\n};\n\n/**\n * Binds the frame buffer to the WebGL context\n */\nFramebuffer.prototype.bind = function()\n{\n\tvar gl = this.gl;\n\n\tif(this.texture)\n\t{\n\t\tthis.texture.unbind();\n\t}\n\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer );\n};\n\n/**\n * Unbinds the frame buffer to the WebGL context\n */\nFramebuffer.prototype.unbind = function()\n{\n\tvar gl = this.gl;\n\tgl.bindFramebuffer(gl.FRAMEBUFFER, null );\t\n};\n/**\n * Resizes the drawing area of the buffer to the given width and height\n * @param width {Number} the new width\n * @param height {Number} the new height\n */\nFramebuffer.prototype.resize = function(width, height)\n{\n\tvar gl = this.gl;\n\n\tthis.width = width;\n\tthis.height = height;\n\n\tif ( this.texture )\n {\n \tthis.texture.uploadData(null, width, height);\n\t}\n\n\tif ( this.stencil )\n {\n // update the stencil buffer width and height\n gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil);\n gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);\n }\n};\n\n/**\n * Destroys this buffer\n */\nFramebuffer.prototype.destroy = function()\n{\n\tvar gl = this.gl;\n\n\t//TODO\n\tif(this.texture)\n\t{\n\t\tthis.texture.destroy();\n\t}\n\n\tgl.deleteFramebuffer(this.framebuffer);\n\n\tthis.gl = null;\n\n\tthis.stencil = null;\n\tthis.texture = null;\n};\n\n/**\n * Creates a frame buffer with a texture containing the given data\n * @mat can you confirm ? :)\n * @static\n * @param gl {WebGLRenderingContext} The current WebGL rendering context\n * @param width {Number} the width of the drawing area of the frame buffer\n * @param height {Number} the height of the drawing area of the frame buffer\n * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data\n */\nFramebuffer.createRGBA = function(gl, width, height, data)\n{\n\tvar texture = Texture.fromData(gl, null, width, height);\n\ttexture.enableNearestScaling();\n texture.enableWrapClamp();\n\n //now create the framebuffer object and attach the texture to it.\n var fbo = new Framebuffer(gl, width, height);\n fbo.enableTexture(texture);\n\n fbo.unbind();\n\n return fbo;\n};\n\n/**\n * Creates a frame buffer with a texture containing the given data\n * @mat not sure what the difference is with the method above ?\n * @static\n * @param gl {WebGLRenderingContext} The current WebGL rendering context\n * @param width {Number} the width of the drawing area of the frame buffer\n * @param height {Number} the height of the drawing area of the frame buffer\n * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data\n */\nFramebuffer.createFloat32 = function(gl, width, height, data)\n{\n\t// create a new texture..\n var texture = new Texture.fromData(gl, data, width, height);\n texture.enableNearestScaling();\n texture.enableWrapClamp();\n\n //now create the framebuffer object and attach the texture to it.\n var fbo = new Framebuffer(gl, width, height);\n fbo.enableTexture(texture);\n\n fbo.unbind();\n\n return fbo;\n};\n\nmodule.exports = Framebuffer;\n\n},{\"./GLTexture\":5}],4:[function(require,module,exports){\n\nvar compileProgram = require('./shader/compileProgram'),\n\textractAttributes = require('./shader/extractAttributes'),\n\textractUniforms = require('./shader/extractUniforms'),\n\tgenerateUniformAccessObject = require('./shader/generateUniformAccessObject');\n\n/**\n * Helper class to create a webGL Shader\n *\n * @class\n * @memberof pixi.gl\n * @param gl {WebGLRenderingContext}\n * @param vertexSrc {string|string[]} The vertex shader source as an array of strings.\n * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings.\n */\nvar Shader = function(gl, vertexSrc, fragmentSrc)\n{\n\t/**\n\t * The current WebGL rendering context\n\t *\n\t * @member {WebGLRenderingContext}\n\t */\n\tthis.gl = gl;\n\n\t/**\n\t * The shader program\n\t *\n\t * @member {WebGLProgram}\n\t */\n\t// First compile the program..\n\tthis.program = compileProgram(gl, vertexSrc, fragmentSrc);\n\n\n\t/**\n\t * The attributes of the shader as an object containing the following properties\n\t * {\n\t * \ttype,\n\t * \tsize,\n\t * \tlocation,\n\t * \tpointer\n\t * }\n\t * @member {Object}\n\t */\n\t// next extract the attributes\n\tthis.attributes = extractAttributes(gl, this.program);\n\n var uniformData = extractUniforms(gl, this.program);\n\n\t/**\n\t * The uniforms of the shader as an object containing the following properties\n\t * {\n\t * \tgl,\n\t * \tdata\n\t * }\n\t * @member {Object}\n\t */\n this.uniforms = generateUniformAccessObject( gl, uniformData );\n};\n/**\n * Uses this shader\n */\nShader.prototype.bind = function()\n{\n\tthis.gl.useProgram(this.program);\n};\n\n/**\n * Destroys this shader\n * TODO\n */\nShader.prototype.destroy = function()\n{\n\tvar gl = this.gl;\n};\n\nmodule.exports = Shader;\n\n},{\"./shader/compileProgram\":9,\"./shader/extractAttributes\":11,\"./shader/extractUniforms\":12,\"./shader/generateUniformAccessObject\":13}],5:[function(require,module,exports){\n\n/**\n * Helper class to create a WebGL Texture\n *\n * @class\n * @memberof pixi.gl\n * @param gl {WebGLRenderingContext} The current WebGL context\n * @param width {number} the width of the texture\n * @param height {number} the height of the texture\n * @param format {number} the pixel format of the texture. defaults to gl.RGBA\n * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE\n */\nvar Texture = function(gl, width, height, format, type)\n{\n\t/**\n\t * The current WebGL rendering context\n\t *\n\t * @member {WebGLRenderingContext}\n\t */\n\tthis.gl = gl;\n\n\n\t/**\n\t * The WebGL texture\n\t *\n\t * @member {WebGLTexture}\n\t */\n\tthis.texture = gl.createTexture();\n\n\t/**\n\t * If mipmapping was used for this texture, enable and disable with enableMipmap()\n\t *\n\t * @member {Boolean}\n\t */\n\t// some settings..\n\tthis.mipmap = false;\n\n\n\t/**\n\t * Set to true to enable pre-multiplied alpha\n\t *\n\t * @member {Boolean}\n\t */\n\tthis.premultiplyAlpha = false;\n\n\t/**\n\t * The width of texture\n\t *\n\t * @member {Number}\n\t */\n\tthis.width = width || 0;\n\t/**\n\t * The height of texture\n\t *\n\t * @member {Number}\n\t */\n\tthis.height = height || 0;\n\n\t/**\n\t * The pixel format of the texture. defaults to gl.RGBA\n\t *\n\t * @member {Number}\n\t */\n\tthis.format = format || gl.RGBA;\n\n\t/**\n\t * The gl type of the texture. defaults to gl.UNSIGNED_BYTE\n\t *\n\t * @member {Number}\n\t */\n\tthis.type = type || gl.UNSIGNED_BYTE;\n\n\n};\n\n/**\n * Uploads this texture to the GPU\n * @param source {HTMLImageElement|ImageData|HTMLVideoElement} the source image of the texture\n */\nTexture.prototype.upload = function(source)\n{\n\tthis.bind();\n\n\tvar gl = this.gl;\n\n\t// if the source is a video, we need to use the videoWidth / videoHeight properties as width / height will be incorrect.\n\tthis.width = source.videoWidth || source.width;\n\tthis.height = source.videoHeight || source.height;\n\n\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha);\n gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source);\n};\n\nvar FLOATING_POINT_AVAILABLE = false;\n\n/**\n * Use a data source and uploads this texture to the GPU\n * @param data {TypedArray} the data to upload to the texture\n * @param width {number} the new width of the texture\n * @param height {number} the new height of the texture\n */\nTexture.prototype.uploadData = function(data, width, height)\n{\n\tthis.bind();\n\n\tvar gl = this.gl;\n\n\tthis.width = width || this.width;\n\tthis.height = height || this.height;\n\n\tif(data instanceof Float32Array)\n\t{\n\t\tif(!FLOATING_POINT_AVAILABLE)\n\t\t{\n\t\t\tvar ext = gl.getExtension(\"OES_texture_float\");\n\n\t\t\tif(ext)\n\t\t\t{\n\t\t\t\tFLOATING_POINT_AVAILABLE = true;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tthrow new Error('floating point textures not available');\n\t\t\t}\n\t\t}\n\n\t\tthis.type = gl.FLOAT;\n\t}\n\telse\n\t{\n\t\t// TODO support for other types\n\t\tthis.type = gl.UNSIGNED_BYTE;\n\t}\n\n\t\n\n\t// what type of data?\n\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha);\n\tgl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null);\n\n};\n\n/**\n * Binds the texture\n * @param location {@mat}\n */\nTexture.prototype.bind = function(location)\n{\n\tvar gl = this.gl;\n\n\tif(location !== undefined)\n\t{\n\t\tgl.activeTexture(gl.TEXTURE0 + location);\n\t}\n\n\tgl.bindTexture(gl.TEXTURE_2D, this.texture);\n};\n\n/**\n * Unbinds the texture\n */\nTexture.prototype.unbind = function()\n{\n\tvar gl = this.gl;\n\tgl.bindTexture(gl.TEXTURE_2D, null);\n};\n\n/**\n * @mat\n * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation\n */\nTexture.prototype.minFilter = function( linear )\n{\n\tvar gl = this.gl;\n\n\tthis.bind();\n\n\tif(this.mipmap)\n\t{\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST);\n\t}\n\telse\n\t{\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST);\n\t}\n};\n\n/**\n * @mat\n * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation\n */\nTexture.prototype.magFilter = function( linear )\n{\n\tvar gl = this.gl;\n\n\tthis.bind();\n\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST);\n};\n\n/**\n * Enables mipmapping\n */\nTexture.prototype.enableMipmap = function()\n{\n\tvar gl = this.gl;\n\n\tthis.bind();\n\n\tthis.mipmap = true;\n\n\tgl.generateMipmap(gl.TEXTURE_2D);\n};\n\n/**\n * Enables linear filtering\n */\nTexture.prototype.enableLinearScaling = function()\n{\n\tthis.minFilter(true);\n\tthis.magFilter(true);\n};\n\n/**\n * Enables nearest neighbour interpolation\n */\nTexture.prototype.enableNearestScaling = function()\n{\n\tthis.minFilter(false);\n\tthis.magFilter(false);\n};\n\n/**\n * Enables clamping on the texture so WebGL will not repeat it\n */\nTexture.prototype.enableWrapClamp = function()\n{\n\tvar gl = this.gl;\n\n\tthis.bind();\n\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n};\n\n/**\n * Enable tiling on the texture\n */\nTexture.prototype.enableWrapRepeat = function()\n{\n\tvar gl = this.gl;\n\n\tthis.bind();\n\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);\n};\n\n/**\n * @mat\n */\nTexture.prototype.enableWrapMirrorRepeat = function()\n{\n\tvar gl = this.gl;\n\n\tthis.bind();\n\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);\n};\n\n\n/**\n * Destroys this texture\n */\nTexture.prototype.destroy = function()\n{\n\tvar gl = this.gl;\n\t//TODO\n\tgl.deleteTexture(this.texture);\n};\n\n/**\n * @static\n * @param gl {WebGLRenderingContext} The current WebGL context\n * @param source {HTMLImageElement|ImageData} the source image of the texture\n * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha\n */\nTexture.fromSource = function(gl, source, premultiplyAlpha)\n{\n\tvar texture = new Texture(gl);\n\ttexture.premultiplyAlpha = premultiplyAlpha || false;\n\ttexture.upload(source);\n\n\treturn texture;\n};\n\n/**\n * @static\n * @param gl {WebGLRenderingContext} The current WebGL context\n * @param data {TypedArray} the data to upload to the texture\n * @param width {number} the new width of the texture\n * @param height {number} the new height of the texture\n */\nTexture.fromData = function(gl, data, width, height)\n{\n\t//console.log(data, width, height);\n\tvar texture = new Texture(gl);\n\ttexture.uploadData(data, width, height);\n\n\treturn texture;\n};\n\n\nmodule.exports = Texture;\n\n},{}],6:[function(require,module,exports){\n\n// state object//\nvar setVertexAttribArrays = require( './setVertexAttribArrays' );\n\n/**\n * Helper class to work with WebGL VertexArrayObjects (vaos)\n * Only works if WebGL extensions are enabled (they usually are)\n *\n * @class\n * @memberof pixi.gl\n * @param gl {WebGLRenderingContext} The current WebGL rendering context\n */\nfunction VertexArrayObject(gl, state)\n{\n\n\tthis.nativeVaoExtension = (\n gl.getExtension('OES_vertex_array_object') ||\n gl.getExtension('MOZ_OES_vertex_array_object') ||\n gl.getExtension('WEBKIT_OES_vertex_array_object')\n );\n\n\tthis.nativeState = state;\n\n\tif(this.nativeVaoExtension)\n\t{\n\t\tthis.nativeVao = this.nativeVaoExtension.createVertexArrayOES();\n\t\t\n\t\tvar maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);\n\t\t\n\t\t// VAO - overwrite the state..\n\t\tthis.nativeState = {\n tempAttribState: new Array(maxAttribs),\n\t\t\tattribState: new Array(maxAttribs)\n };\n\t}\n\n\t/**\n\t * The current WebGL rendering context\n\t *\n\t * @member {WebGLRenderingContext}\n\t */\n\tthis.gl = gl;\n\n\t/**\n\t * An array of attributes ? @mat\n\t *\n\t * @member {Array}\n\t */\n\tthis.attributes = [];\n\n\t/**\n\t * @mat\n\t *\n\t * @member {Array}\n\t */\n\tthis.indexBuffer = null;\n\n\t/**\n\t * A boolean flag\n\t *\n\t * @member {Boolean}\n\t */\n\tthis.dirty = false;\n}\n\nVertexArrayObject.prototype.constructor = VertexArrayObject;\nmodule.exports = VertexArrayObject;\n\n\n/**\n * Binds the buffer\n */\nVertexArrayObject.prototype.bind = function()\n{\n\tif(this.nativeVao)\n\t{\n\t\tthis.nativeVaoExtension.bindVertexArrayOES(this.nativeVao);\n\n\t\tif(this.dirty)\n\t\t{\n\t\t\tthis.dirty = false;\n\t\t\tthis.activate();\n\t\t}\n\t}\n\telse\n\t{\n\t\t\n\t\tthis.activate();\n\t}\n\n\treturn this;\n};\n\n/**\n * Unbinds the buffer\n */\nVertexArrayObject.prototype.unbind = function()\n{\n\tif(this.nativeVao)\n\t{\n\t\tthis.nativeVaoExtension.bindVertexArrayOES(null);\n\t}\n\n\treturn this;\n};\n\n/**\n * Uses this vao\n */\nVertexArrayObject.prototype.activate = function()\n{\n\t\n\tvar gl = this.gl;\n\tvar lastBuffer = null;\n\n\tfor (var i = 0; i < this.attributes.length; i++)\n\t{\n\t\tvar attrib = this.attributes[i];\n\n\t\tif(lastBuffer !== attrib.buffer)\n\t\t{\n\t\t\tattrib.buffer.bind();\n\t\t\tlastBuffer = attrib.buffer;\n\t\t}\n\n\t\t//attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start);\n\t\tgl.vertexAttribPointer(attrib.attribute.location,\n\t\t\t\t\t\t\t attrib.attribute.size, attrib.type || gl.FLOAT,\n\t\t\t\t\t\t\t attrib.normalized || false,\n\t\t\t\t\t\t\t attrib.stride || 0,\n\t\t\t\t\t\t\t attrib.start || 0);\n\n\n\t}\n\n\tsetVertexAttribArrays(gl, this.attributes, this.nativeState);\n\t\n\tthis.indexBuffer.bind();\n\n\treturn this;\n};\n\n/**\n *\n * @param buffer {WebGLBuffer}\n * @param attribute {[type]}\n * @param type {[type]}\n * @param normalized {[type]}\n * @param stride {Number}\n * @param start {Number}\n */\nVertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start)\n{\n this.attributes.push({\n \tbuffer: \tbuffer,\n \tattribute: \tattribute,\n\n \tlocation: \tattribute.location,\n\t \ttype: \t\ttype || this.gl.FLOAT,\n\t \tnormalized: normalized || false,\n\t \tstride: \tstride || 0,\n\t \tstart: \t\tstart || 0\n\t});\n\n\tthis.dirty = true;\n\n\treturn this;\n};\n\n/**\n *\n * @param buffer {WebGLBuffer}\n * @param options {Object}\n */\nVertexArrayObject.prototype.addIndex = function(buffer, options)\n{\n this.indexBuffer = buffer;\n\n this.dirty = true;\n\n return this;\n};\n\n/**\n * Unbinds this vao and disables it\n */\nVertexArrayObject.prototype.clear = function()\n{\n\tvar gl = this.gl;\n\n\t// TODO - should this function unbind after clear?\n\t// for now, no but lets see what happens in the real world!\n\tif(this.nativeVao)\n\t{\n\t\tthis.nativeVaoExtension.bindVertexArrayOES(this.nativeVao);\n\t}\n\n\tthis.attributes.length = 0;\n\tthis.indexBuffer = null;\n\n\treturn this;\n};\n\n/**\n * @mat\n * @param type {Number}\n * @param size {Number}\n * @param start {Number}\n */\nVertexArrayObject.prototype.draw = function(type, size, start)\n{\n\tvar gl = this.gl;\n\tgl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0);\n\n\treturn this;\n};\n\n/**\n * Destroy this vao\n */\nVertexArrayObject.prototype.destroy = function()\n{\n\t// lose references\n\tthis.gl = null;\n\tthis.indexBuffer = null;\n\tthis.attributes = null;\n\tthis.nativeState = null;\n\n\tif(this.nativeVao)\n\t{\n\t\tthis.nativeVaoExtension.deleteVertexArrayOES(this.nativeVao);\n\t}\n\n\tthis.nativeVaoExtension = null;\n\tthis.nativeVao = null;\n};\n\n},{\"./setVertexAttribArrays\":8}],7:[function(require,module,exports){\n\n/**\n * Helper class to create a webGL Context\n *\n * @class\n * @memberof pixi.gl\n * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from\n * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes,\n * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available\n * @return {WebGLRenderingContext} the WebGL context\n */\nvar createContext = function(canvas, options)\n{\n var gl = canvas.getContext('webgl', options) || \n \t canvas.getContext('experimental-webgl', options);\n\n if (!gl)\n {\n // fail, not able to get a context\n throw new Error('This browser does not support webGL. Try using the canvas renderer');\n }\n\n return gl;\n};\n\nmodule.exports = createContext;\n\n},{}],8:[function(require,module,exports){\nvar GL_MAP = {};\n\n/**\n * @mat\n * @param gl {WebGLRenderingContext} The current WebGL context\n * @param attribs {[type]}\n */\nvar setVertexAttribArrays = function (gl, attribs, state)\n{\n var i;\n if(state)\n {\n var tempAttribState = state.tempAttribState,\n attribState = state.attribState;\n\n for (i = 0; i < tempAttribState.length; i++)\n {\n tempAttribState[i] = false;\n }\n\n // set the new attribs\n for (i = 0; i < attribs.length; i++)\n {\n tempAttribState[attribs[i].attribute.location] = true;\n }\n\n for (i = 0; i < attribState.length; i++)\n {\n if (attribState[i] !== tempAttribState[i])\n {\n attribState[i] = tempAttribState[i];\n\n if (state.attribState[i])\n {\n gl.enableVertexAttribArray(i);\n }\n else\n {\n gl.disableVertexAttribArray(i);\n }\n }\n }\n\n }\n else\n {\n for (i = 0; i < attribs.length; i++)\n {\n var attrib = attribs[i];\n gl.enableVertexAttribArray(attrib.attribute.location);\n }\n }\n};\n\nmodule.exports = setVertexAttribArrays;\n\n},{}],9:[function(require,module,exports){\n\n/**\n *\n * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram}\n * @param vertexSrc {string|string[]} The vertex shader source as an array of strings.\n * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings.\n * @return {WebGLProgram} the shader program\n */\nvar compileProgram = function(gl, vertexSrc, fragmentSrc)\n{\n var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc);\n var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);\n\n var program = gl.createProgram();\n\n gl.attachShader(program, glVertShader);\n gl.attachShader(program, glFragShader);\n gl.linkProgram(program);\n\n // if linking fails, then log and cleanup\n if (!gl.getProgramParameter(program, gl.LINK_STATUS))\n {\n console.error('Pixi.js Error: Could not initialize shader.');\n console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS));\n console.error('gl.getError()', gl.getError());\n\n // if there is a program info log, log it\n if (gl.getProgramInfoLog(program) !== '')\n {\n console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program));\n }\n\n gl.deleteProgram(program);\n program = null;\n }\n\n // clean up some shaders\n gl.deleteShader(glVertShader);\n gl.deleteShader(glFragShader);\n\n return program;\n};\n\n/**\n *\n * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram}\n * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER\n * @param vertexSrc {string|string[]} The vertex shader source as an array of strings.\n * @return {WebGLShader} the shader\n */\nvar compileShader = function (gl, type, src)\n{\n var shader = gl.createShader(type);\n\n gl.shaderSource(shader, src);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))\n {\n console.log(gl.getShaderInfoLog(shader));\n return null;\n }\n\n return shader;\n};\n\nmodule.exports = compileProgram;\n\n},{}],10:[function(require,module,exports){\n\n\nvar defaultValue = function(type, size) \n{\n switch (type)\n {\n case 'float':\n return 0;\n\n case 'vec2': \n return new Float32Array(2 * size);\n\n case 'vec3':\n return new Float32Array(3 * size);\n\n case 'vec4': \n return new Float32Array(4 * size);\n \n case 'int':\n case 'sampler2D':\n return 0;\n\n case 'ivec2': \n return new Int32Array(2 * size);\n\n case 'ivec3':\n return new Int32Array(3 * size);\n\n case 'ivec4': \n return new Int32Array(4 * size);\n\n case 'bool': \n return false;\n\n case 'bvec2':\n\n return booleanArray( 2 * size);\n\n case 'bvec3':\n return booleanArray(3 * size);\n\n case 'bvec4':\n return booleanArray(4 * size);\n\n case 'mat2':\n return new Float32Array([1, 0,\n 0, 1]);\n\n case 'mat3': \n return new Float32Array([1, 0, 0,\n 0, 1, 0,\n 0, 0, 1]);\n\n case 'mat4':\n return new Float32Array([1, 0, 0, 0,\n 0, 1, 0, 0,\n 0, 0, 1, 0,\n 0, 0, 0, 1]);\n }\n};\n\nvar booleanArray = function(size)\n{\n var array = new Array(size);\n\n for (var i = 0; i < array.length; i++) \n {\n array[i] = false;\n }\n\n return array;\n};\n\nmodule.exports = defaultValue;\n\n},{}],11:[function(require,module,exports){\n\nvar mapType = require('./mapType');\nvar mapSize = require('./mapSize');\n\n/**\n * Extracts the attributes\n * @param gl {WebGLRenderingContext} The current WebGL rendering context\n * @param program {WebGLProgram} The shader program to get the attributes from\n * @return attributes {Object}\n */\nvar extractAttributes = function(gl, program)\n{\n var attributes = {};\n\n var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);\n\n for (var i = 0; i < totalAttributes; i++)\n {\n var attribData = gl.getActiveAttrib(program, i);\n var type = mapType(gl, attribData.type);\n\n attributes[attribData.name] = {\n type:type,\n size:mapSize(type),\n location:gl.getAttribLocation(program, attribData.name),\n //TODO - make an attribute object\n pointer: pointer\n };\n }\n\n return attributes;\n};\n\nvar pointer = function(type, normalized, stride, start){\n // console.log(this.location)\n gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0);\n};\n\nmodule.exports = extractAttributes;\n\n},{\"./mapSize\":14,\"./mapType\":15}],12:[function(require,module,exports){\nvar mapType = require('./mapType');\nvar defaultValue = require('./defaultValue');\n\n/**\n * Extracts the uniforms\n * @param gl {WebGLRenderingContext} The current WebGL rendering context\n * @param program {WebGLProgram} The shader program to get the uniforms from\n * @return uniforms {Object}\n */\nvar extractUniforms = function(gl, program)\n{\n\tvar uniforms = {};\n\n var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);\n\n for (var i = 0; i < totalUniforms; i++)\n {\n \tvar uniformData = gl.getActiveUniform(program, i);\n \tvar name = uniformData.name.replace(/\\[.*?\\]/, \"\");\n var type = mapType(gl, uniformData.type );\n\n \tuniforms[name] = {\n \t\ttype:type,\n \t\tsize:uniformData.size,\n \t\tlocation:gl.getUniformLocation(program, name),\n \t\tvalue:defaultValue(type, uniformData.size)\n \t};\n }\n\n\treturn uniforms;\n};\n\nmodule.exports = extractUniforms;\n\n},{\"./defaultValue\":10,\"./mapType\":15}],13:[function(require,module,exports){\n/**\n * Extracts the attributes\n * @param gl {WebGLRenderingContext} The current WebGL rendering context\n * @param uniforms {Array} @mat ?\n * @return attributes {Object}\n */\nvar generateUniformAccessObject = function(gl, uniformData)\n{\n // this is the object we will be sending back.\n // an object hierachy will be created for structs\n var uniforms = {data:{}};\n\n uniforms.gl = gl;\n\n var uniformKeys= Object.keys(uniformData);\n\n for (var i = 0; i < uniformKeys.length; i++)\n {\n var fullName = uniformKeys[i];\n\n var nameTokens = fullName.split('.');\n var name = nameTokens[nameTokens.length - 1];\n\n var uniformGroup = getUniformGroup(nameTokens, uniforms);\n\n var uniform = uniformData[fullName];\n uniformGroup.data[name] = uniform;\n\n uniformGroup.gl = gl;\n\n Object.defineProperty(uniformGroup, name, {\n get: generateGetter(name),\n set: generateSetter(name, uniform)\n });\n }\n\n return uniforms;\n};\n\nvar generateGetter = function(name)\n{\n\tvar template = getterTemplate.replace('%%', name);\n\treturn new Function(template); // jshint ignore:line\n};\n\nvar generateSetter = function(name, uniform)\n{\n var template = setterTemplate.replace(/%%/g, name);\n var setTemplate;\n\n if(uniform.size === 1)\n {\n setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type];\n }\n else\n {\n setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type];\n }\n\n if(setTemplate)\n {\n template += \"\\nthis.gl.\" + setTemplate + \";\";\n }\n\n \treturn new Function('value', template); // jshint ignore:line\n};\n\nvar getUniformGroup = function(nameTokens, uniform)\n{\n var cur = uniform;\n\n for (var i = 0; i < nameTokens.length - 1; i++)\n {\n var o = cur[nameTokens[i]] || {data:{}};\n cur[nameTokens[i]] = o;\n cur = o;\n }\n\n return cur;\n};\n\nvar getterTemplate = [\n 'return this.data.%%.value;',\n].join('\\n');\n\nvar setterTemplate = [\n 'this.data.%%.value = value;',\n 'var location = this.data.%%.location;'\n].join('\\n');\n\n\nvar GLSL_TO_SINGLE_SETTERS = {\n\n 'float': 'uniform1f(location, value)',\n\n 'vec2': 'uniform2f(location, value[0], value[1])',\n 'vec3': 'uniform3f(location, value[0], value[1], value[2])',\n 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])',\n\n 'int': 'uniform1i(location, value)',\n 'ivec2': 'uniform2i(location, value[0], value[1])',\n 'ivec3': 'uniform3i(location, value[0], value[1], value[2])',\n 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])',\n\n 'bool': 'uniform1i(location, value)',\n 'bvec2': 'uniform2i(location, value[0], value[1])',\n 'bvec3': 'uniform3i(location, value[0], value[1], value[2])',\n 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])',\n\n 'mat2': 'uniformMatrix2fv(location, false, value)',\n 'mat3': 'uniformMatrix3fv(location, false, value)',\n 'mat4': 'uniformMatrix4fv(location, false, value)',\n\n 'sampler2D':'uniform1i(location, value)'\n};\n\nvar GLSL_TO_ARRAY_SETTERS = {\n\n 'float': 'uniform1fv(location, value)',\n\n 'vec2': 'uniform2fv(location, value)',\n 'vec3': 'uniform3fv(location, value)',\n 'vec4': 'uniform4fv(location, value)',\n\n 'int': 'uniform1iv(location, value)',\n 'ivec2': 'uniform2iv(location, value)',\n 'ivec3': 'uniform3iv(location, value)',\n 'ivec4': 'uniform4iv(location, value)',\n\n 'bool': 'uniform1iv(location, value)',\n 'bvec2': 'uniform2iv(location, value)',\n 'bvec3': 'uniform3iv(location, value)',\n 'bvec4': 'uniform4iv(location, value)',\n\n 'sampler2D':'uniform1iv(location, value)'\n};\n\nmodule.exports = generateUniformAccessObject;\n\n},{}],14:[function(require,module,exports){\n\n\nvar mapSize = function(type) \n{ \n return GLSL_TO_SIZE[type];\n};\n\n\nvar GLSL_TO_SIZE = {\n 'float': 1,\n 'vec2': 2,\n 'vec3': 3,\n 'vec4': 4,\n\n 'int': 1,\n 'ivec2': 2,\n 'ivec3': 3,\n 'ivec4': 4,\n\n 'bool': 1,\n 'bvec2': 2,\n 'bvec3': 3,\n 'bvec4': 4,\n\n 'mat2': 4,\n 'mat3': 9,\n 'mat4': 16,\n\n 'sampler2D': 1\n};\n\nmodule.exports = mapSize;\n\n},{}],15:[function(require,module,exports){\n\n\nvar mapSize = function(gl, type) \n{\n if(!GL_TABLE) \n {\n var typeNames = Object.keys(GL_TO_GLSL_TYPES);\n\n GL_TABLE = {};\n\n for(var i = 0; i < typeNames.length; ++i) \n {\n var tn = typeNames[i];\n GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn];\n }\n }\n\n return GL_TABLE[type];\n};\n\nvar GL_TABLE = null;\n\nvar GL_TO_GLSL_TYPES = {\n 'FLOAT': 'float',\n 'FLOAT_VEC2': 'vec2',\n 'FLOAT_VEC3': 'vec3',\n 'FLOAT_VEC4': 'vec4',\n\n 'INT': 'int',\n 'INT_VEC2': 'ivec2',\n 'INT_VEC3': 'ivec3',\n 'INT_VEC4': 'ivec4',\n \n 'BOOL': 'bool',\n 'BOOL_VEC2': 'bvec2',\n 'BOOL_VEC3': 'bvec3',\n 'BOOL_VEC4': 'bvec4',\n \n 'FLOAT_MAT2': 'mat2',\n 'FLOAT_MAT3': 'mat3',\n 'FLOAT_MAT4': 'mat4',\n \n 'SAMPLER_2D': 'sampler2D' \n};\n\nmodule.exports = mapSize;\n\n},{}],16:[function(require,module,exports){\n(function (process,global){\n/*!\n * async\n * https://github.com/caolan/async\n *\n * Copyright 2010-2014 Caolan McMahon\n * Released under the MIT license\n */\n(function () {\n\n var async = {};\n function noop() {}\n function identity(v) {\n return v;\n }\n function toBool(v) {\n return !!v;\n }\n function notId(v) {\n return !v;\n }\n\n // global on the server, window in the browser\n var previous_async;\n\n // Establish the root object, `window` (`self`) in the browser, `global`\n // on the server, or `this` in some virtual machines. We use `self`\n // instead of `window` for `WebWorker` support.\n var root = typeof self === 'object' && self.self === self && self ||\n typeof global === 'object' && global.global === global && global ||\n this;\n\n if (root != null) {\n previous_async = root.async;\n }\n\n async.noConflict = function () {\n root.async = previous_async;\n return async;\n };\n\n function only_once(fn) {\n return function() {\n if (fn === null) throw new Error(\"Callback was already called.\");\n fn.apply(this, arguments);\n fn = null;\n };\n }\n\n function _once(fn) {\n return function() {\n if (fn === null) return;\n fn.apply(this, arguments);\n fn = null;\n };\n }\n\n //// cross-browser compatiblity functions ////\n\n var _toString = Object.prototype.toString;\n\n var _isArray = Array.isArray || function (obj) {\n return _toString.call(obj) === '[object Array]';\n };\n\n // Ported from underscore.js isObject\n var _isObject = function(obj) {\n var type = typeof obj;\n return type === 'function' || type === 'object' && !!obj;\n };\n\n function _isArrayLike(arr) {\n return _isArray(arr) || (\n // has a positive integer length property\n typeof arr.length === \"number\" &&\n arr.length >= 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