diff --git a/bin/pixi.js b/bin/pixi.js index 85518a9..1d99b5e 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -1,4 +1,1164 @@ (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; +} + +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); +} + +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 + * @param gl {WebGLRenderingContext} + */ + +var Framebuffer = function(gl, width, height) +{ + this.gl = gl; + + this.framebuffer = gl.createFramebuffer(); + + this.stencil = null; + this.texture = null; + + this.width = width || 100; + this.height = height || 100; +} + +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); +} + +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 ); +} + +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); +} + +Framebuffer.prototype.bind = function() +{ + var gl = this.gl; + + if(this.texture) + { + this.texture.unbind(); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); +} + +Framebuffer.prototype.unbind = function() +{ + gl.bindFramebuffer(gl.FRAMEBUFFER, null ); +} + +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); + } +} + +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; +} + +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; +} + +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 + * @param gl {WebGLRenderingContext} + */ +var Shader = function(gl, vertexSrc, fragmentSrc) +{ + this.gl = gl; + + // First compile the program.. + this.program = compileProgram(gl, vertexSrc, fragmentSrc); + + // next extract the attributes + this.attributes = extractAttributes(gl, this.program); + + var uniformData = extractUniforms(gl, this.program); + + this.uniforms = generateUniformAccessObject( gl, uniformData ); +} + +Shader.prototype.bind = function() +{ + this.gl.useProgram(this.program); +} + +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 + * @param gl {WebGLRenderingContext} a 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) +{ + this.gl = gl; + + this.texture = gl.createTexture(); + + // some settings.. + this.mipmap = false; + + this.premultiplyAlpha = false; + + this.width = width || 0; + this.height = height || 0; + + this.format = format || gl.RGBA; + this.type = type || gl.UNSIGNED_BYTE; + + +} + +/** + * @param {PIXI.glCore.Texture} [varname] [description] + */ +Texture.prototype.upload = function(source) +{ + this.bind(); + + var gl = this.gl; + + this.width = source.width; + this.height = 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; + +Texture.prototype.uploadData = function(data, width, height) +{ + this.bind(); + + 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); + +} + +Texture.prototype.bind = function(location) +{ + var gl = this.gl; + + if(location !== undefined) + { + gl.activeTexture(gl.TEXTURE0 + location); + } + + gl.bindTexture(gl.TEXTURE_2D, this.texture); +} + +Texture.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindTexture(gl.TEXTURE_2D, null); +} + +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); + } +} + +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); +} + +Texture.prototype.enableMipmap = function() +{ + this.bind(); + + this.mipmap = true; + gl.generateMipmap(gl.TEXTURE_2D); +} + +Texture.prototype.enableLinearScaling = function() +{ + this.minFilter(true); + this.magFilter(true); +} + +Texture.prototype.enableNearestScaling = function() +{ + this.minFilter(false); + this.magFilter(false); +} + +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); +} + +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); +} + +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); +} + + + +Texture.prototype.destroy = function() +{ + var gl = this.gl; + //TODO + gl.deleteTexture(this.texture); +} + +//Texture. +Texture.fromSource = function(gl, source, premultiplyAlpha) +{ + var texture = new Texture(gl); + texture.premultiplyAlpha = premultiplyAlpha || false; + texture.upload(source); + + return 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){ + +/** + * Generic Mask Stack data structure + * @class + * @memberof PIXI + */ + +// state object// + + +function VertexArrayObject(gl) +{ + + this.nativeVaoExtension = ( + gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object') + ); + +// this.nativeVaoExtension = null; + + if(this.nativeVaoExtension) + { + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + } + + this.gl = gl; + + this.attributes = []; + + this.indexBuffer = null; + + this.dirty = false; + + +} + +VertexArrayObject.prototype.constructor = VertexArrayObject; +module.exports = VertexArrayObject; + +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; +} + +VertexArrayObject.prototype.unbind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + return this; +} + +VertexArrayObject.prototype.activate = function() +{ + var gl = this.gl; + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + attrib.buffer.bind(); + + //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); + + gl.enableVertexAttribArray(attrib.attribute.location); + }; + + this.indexBuffer.bind(); + + return this; +} + +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; +} + + +VertexArrayObject.prototype.addIndex = function(buffer, options) +{ + this.indexBuffer = buffer; + + this.dirty = true; + + return this; +} + +VertexArrayObject.prototype.clear = function() +{ + // 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); + } + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + gl.disableVertexAttribArray(attrib.attribute.location); + }; + + this.attributes.length = 0; + this.indexBuffer = null; + + return this; +} + +VertexArrayObject.prototype.draw = function(type, size, start) +{ + var gl = this.gl; + gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); + + return this; +} + + +},{}],7:[function(require,module,exports){ + +/** + * Helper class to create a webGL Context + * + * @class + * @memberof PIXI + * @param gl {WebGLRenderingContext} + */ + + + +var createContext = function(canvas, options) +{ + 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){ +/** + * Generic Mask Stack data structure + * @class + * @memberof PIXI + */ + +var GL_MAP = {}; + + +var setVertexAttribArrays = function (gl, attribs) +{ + // console.log(gl.id) + var data = GL_MAP[gl.id]; + + if(!data) + { + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + data = GL_MAP[gl.id] = {tempAttribState:new Array(maxAttribs) + ,attribState:new Array(maxAttribs)}; + } + + var i, + tempAttribState = data.tempAttribState, + attribState = data.attribState; + + for (i = 0; i < tempAttribState.length; i++) + { + tempAttribState[i] = false; + } + + // set the new attribs + for (i in attribs) + { + tempAttribState[attribs[i].location] = true; + } + + for (i = 1; i < attribState.length; i++) + { + if (attribState[i] !== tempAttribState[i]) + { + attribState[i] = tempAttribState[i]; + + if (data.attribState[i]) + { + gl.enableVertexAttribArray(i); + } + else + { + gl.disableVertexAttribArray(i); + } + } + } +}; + +module.exports = setVertexAttribArrays; +},{}],9:[function(require,module,exports){ + + + + +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; +} + +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'); + +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:function(type, normalized, stride, start){ + + // console.log(this.location) + gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); + + } + } + }; + + return attributes; +} + +module.exports = extractAttributes; + + +},{"./mapSize":14,"./mapType":15}],12:[function(require,module,exports){ +var mapType = require('./mapType'); +var defaultValue = require('./defaultValue'); + + +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){ + +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); +} + +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); +} + +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 @@ -1267,7 +2427,7 @@ }()); }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":5}],2:[function(require,module,exports){ +},{"_process":20}],17:[function(require,module,exports){ /** * Bit twiddling hacks for JavaScript. * @@ -1473,9 +2633,9 @@ } -},{}],3:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ -},{}],4:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -1703,7 +2863,7 @@ ; }).call(this,require('_process')) -},{"_process":5}],5:[function(require,module,exports){ +},{"_process":20}],20:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -1796,7 +2956,7 @@ }; process.umask = function() { return 0; }; -},{}],6:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ (function (global){ /*! https://mths.be/punycode v1.4.0 by @mathias */ ;(function(root) { @@ -2333,7 +3493,7 @@ }(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],7:[function(require,module,exports){ +},{}],22:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -2419,7 +3579,7 @@ return Object.prototype.toString.call(xs) === '[object Array]'; }; -},{}],8:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -2506,13 +3666,13 @@ return res; }; -},{}],9:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ 'use strict'; exports.decode = exports.parse = require('./decode'); exports.encode = exports.stringify = require('./encode'); -},{"./decode":7,"./encode":8}],10:[function(require,module,exports){ +},{"./decode":22,"./encode":23}],25:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -3221,7 +4381,7 @@ return arg == null; } -},{"punycode":6,"querystring":9}],11:[function(require,module,exports){ +},{"punycode":21,"querystring":24}],26:[function(require,module,exports){ 'use strict'; module.exports = earcut; @@ -3807,7 +4967,7 @@ this.steiner = false; } -},{}],12:[function(require,module,exports){ +},{}],27:[function(require,module,exports){ 'use strict'; // @@ -4071,7 +5231,7 @@ module.exports = EventEmitter; } -},{}],13:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ /* eslint-disable no-unused-vars */ 'use strict'; var hasOwnProperty = Object.prototype.hasOwnProperty; @@ -4112,1155 +5272,6 @@ 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){ - -/** - * Helper class to create a webGL buffer - * - * @class - * @memberof PIXI - * @param gl {WebGLRenderingContext} - */ - -var EMPTY_ARRAY_BUFFER = new ArrayBuffer(0); - -var Buffer = function(gl, type, data, drawType) -{ - this.gl = gl; - - this.buffer = gl.createBuffer(); - this.type = type || gl.ARRAY_BUFFER; - this.drawType = drawType || gl.STATIC_DRAW; - this.data = EMPTY_ARRAY_BUFFER; - - if(data) - { - this.upload(data); - } -} - - -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; -} - -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); -} - -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 - * @param gl {WebGLRenderingContext} - */ - -var Framebuffer = function(gl, width, height) -{ - this.gl = gl; - - this.framebuffer = gl.createFramebuffer(); - - this.stencil = null; - this.texture = null; - - this.width = width || 100; - this.height = height || 100; -} - -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); -} - -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 ); -} - -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); -} - -Framebuffer.prototype.bind = function() -{ - var gl = this.gl; - - if(this.texture) - { - this.texture.unbind(); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); -} - -Framebuffer.prototype.unbind = function() -{ - gl.bindFramebuffer(gl.FRAMEBUFFER, null ); -} - -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); - } -} - -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; -} - -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; -} - -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 - * @param gl {WebGLRenderingContext} - */ -var Shader = function(gl, vertexSrc, fragmentSrc) -{ - this.gl = gl; - - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc); - - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - var uniformData = extractUniforms(gl, this.program); - - this.uniforms = generateUniformAccessObject( gl, uniformData ); -} - -Shader.prototype.bind = function() -{ - this.gl.useProgram(this.program); -} - -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 - * @param gl {WebGLRenderingContext} a 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) -{ - this.gl = gl; - - this.texture = gl.createTexture(); - - // some settings.. - this.mipmap = false; - - this.premultiplyAlpha = false; - - this.width = width || 0; - this.height = height || 0; - - this.format = format || gl.RGBA; - this.type = type || gl.UNSIGNED_BYTE; - - -} - -/** - * @param {PIXI.glCore.Texture} [varname] [description] - */ -Texture.prototype.upload = function(source) -{ - this.bind(); - - var gl = this.gl; - - this.width = source.width; - this.height = 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; - -Texture.prototype.uploadData = function(data, width, height) -{ - this.bind(); - - 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); - -} - -Texture.prototype.bind = function(location) -{ - var gl = this.gl; - - if(location !== undefined) - { - gl.activeTexture(gl.TEXTURE0 + location); - } - - gl.bindTexture(gl.TEXTURE_2D, this.texture); -} - -Texture.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, null); -} - -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); - } -} - -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); -} - -Texture.prototype.enableMipmap = function() -{ - this.bind(); - - this.mipmap = true; - gl.generateMipmap(gl.TEXTURE_2D); -} - -Texture.prototype.enableLinearScaling = function() -{ - this.minFilter(true); - this.magFilter(true); -} - -Texture.prototype.enableNearestScaling = function() -{ - this.minFilter(false); - this.magFilter(false); -} - -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); -} - -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); -} - -Texture.prototype.destroy = function() -{ - var gl = this.gl; - //TODO - gl.deleteTexture(this.texture); -} - -//Texture. -Texture.fromSource = function(gl, source, premultiplyAlpha) -{ - var texture = new Texture(gl); - texture.premultiplyAlpha = premultiplyAlpha || false; - texture.upload(source); - - return 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){ - -/** - * Generic Mask Stack data structure - * @class - * @memberof PIXI - */ - -// state object// - - -function VertexArrayObject(gl) -{ - - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); - -// this.nativeVaoExtension = null; - - if(this.nativeVaoExtension) - { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - } - - this.gl = gl; - - this.attributes = []; - - this.indexBuffer = null; - - this.dirty = false; - - -} - -VertexArrayObject.prototype.constructor = VertexArrayObject; -module.exports = VertexArrayObject; - -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; -} - -VertexArrayObject.prototype.unbind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(null); - } - - return this; -} - -VertexArrayObject.prototype.activate = function() -{ - var gl = this.gl; - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - attrib.buffer.bind(); - - //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); - - gl.enableVertexAttribArray(attrib.attribute.location); - }; - - this.indexBuffer.bind(); - - return this; -} - -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; -} - - -VertexArrayObject.prototype.addIndex = function(buffer, options) -{ - this.indexBuffer = buffer; - - this.dirty = true; - - return this; -} - -VertexArrayObject.prototype.clear = function() -{ - // 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); - } - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - gl.disableVertexAttribArray(attrib.attribute.location); - }; - - this.attributes.length = 0; - this.indexBuffer = null; - - return this; -} - -VertexArrayObject.prototype.draw = function(type, size, start) -{ - var gl = this.gl; - gl.drawElements(type, size, gl.UNSIGNED_SHORT, start); - - return this; -} - - -},{}],20:[function(require,module,exports){ - -/** - * Helper class to create a webGL Context - * - * @class - * @memberof PIXI - * @param gl {WebGLRenderingContext} - */ - - - -var createContext = function(canvas, options) -{ - 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){ -/** - * Generic Mask Stack data structure - * @class - * @memberof PIXI - */ - -var GL_MAP = {}; - - -var setVertexAttribArrays = function (gl, attribs) -{ - // console.log(gl.id) - var data = GL_MAP[gl.id]; - - if(!data) - { - var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - data = GL_MAP[gl.id] = {tempAttribState:new Array(maxAttribs) - ,attribState:new Array(maxAttribs)}; - } - - var i, - tempAttribState = data.tempAttribState, - attribState = data.attribState; - - for (i = 0; i < tempAttribState.length; i++) - { - tempAttribState[i] = false; - } - - // set the new attribs - for (i in attribs) - { - tempAttribState[attribs[i].location] = true; - } - - for (i = 1; i < attribState.length; i++) - { - if (attribState[i] !== tempAttribState[i]) - { - attribState[i] = tempAttribState[i]; - - if (data.attribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } - } - } -}; - -module.exports = setVertexAttribArrays; -},{}],22:[function(require,module,exports){ - - - - -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; -} - -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'); - -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:function(type, normalized, stride, start){ - - // console.log(this.location) - gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); - - } - } - }; - - return attributes; -} - -module.exports = extractAttributes; - - -},{"./mapSize":27,"./mapType":28}],25:[function(require,module,exports){ -var mapType = require('./mapType'); -var defaultValue = require('./defaultValue'); - - -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){ - -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); -} - -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); -} - -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){ /*! @@ -6388,7 +6399,7 @@ }()); }).call(this,require('_process')) -},{"_process":5}],30:[function(require,module,exports){ +},{"_process":20}],30:[function(require,module,exports){ var async = require('async'), urlParser = require('url'), Resource = require('./Resource'), @@ -6846,7 +6857,7 @@ Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; -},{"./Resource":31,"async":29,"eventemitter3":12,"url":10}],31:[function(require,module,exports){ +},{"./Resource":31,"async":29,"eventemitter3":27,"url":25}],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 @@ -7648,7 +7659,7 @@ map[extname] = val; } -},{"eventemitter3":12,"url":10}],32:[function(require,module,exports){ +},{"eventemitter3":27,"url":25}],32:[function(require,module,exports){ module.exports = { // private property @@ -8431,6 +8442,37 @@ }, /** + * The wrap modes that are supported by pixi. + * + * The DEFAULT wrap mode affects the default wraping mode of future operations. + * It can be re-assigned to either CLAMP or REPEAT, depending upon suitability. + * If the texture is non power of two then clamp will be used regardless as webGL can only use REPEAT if the texture is po2 + * This property only affects WebGL + * @static + * @constant + * @property {object} WRAP_MODES + * @property {number} WRAP_MODES.DEFAULT=CLAMP + * @property {number} WRAP_MODES.CLAMP The textures uvs are clamped + * @property {number} WRAP_MODES.REPEAT The texture uvs tile and repeat + * @property {number} WRAP_MODES.MIRRORED_REPEAT The texture uvs tile and repeat with mirroring + */ + WRAP_MODES: { + DEFAULT: 0, + CLAMP: 0, + REPEAT: 1, + MIRRORED_REPEAT:2 + }, + + /** + * If set to true WebGL will attempt make textures mimpaped by default + * Mipmapping will only succeed if the base texture uploaded has power of two dimensions + * @static + * @constant + * @property {bool} MIPMAP_TEXTURES + */ + MIPMAP_TEXTURES:true, + + /** * The prefix that denotes a URL is for a retina asset * * @static @@ -9639,7 +9681,7 @@ this.filterArea = null; }; -},{"../const":40,"../math":61,"../textures/RenderTexture":97,"./Transform":43,"eventemitter3":12}],43:[function(require,module,exports){ +},{"../const":40,"../math":61,"../textures/RenderTexture":97,"./Transform":43,"eventemitter3":27}],43:[function(require,module,exports){ var math = require('../math'); @@ -11544,7 +11586,7 @@ this.glIndices = null; }; -},{"pixi-gl-core":14}],50:[function(require,module,exports){ +},{"pixi-gl-core":1}],50:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -11596,7 +11638,7 @@ module.exports = PrimitiveShader; -},{"pixi-gl-core":14}],51:[function(require,module,exports){ +},{"pixi-gl-core":1}],51:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -12054,7 +12096,7 @@ module.exports = buildPoly; -},{"../../../utils":104,"./buildLine":53,"earcut":11}],55:[function(require,module,exports){ +},{"../../../utils":104,"./buildLine":53,"earcut":26}],55:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -12277,9 +12319,7 @@ // sprites Sprite: require('./sprites/Sprite'), CanvasSpriteRender: require('./sprites/canvas/CanvasSpriteRenderer'), - //ParticleContainer: require('./particles/ParticleContainer'), SpriteRenderer: require('./sprites/webgl/SpriteRenderer'), - //ParticleRenderer: require('./particles/webgl/ParticleRenderer'), // text Text: require('./text/Text'), @@ -12347,7 +12387,7 @@ } }); -},{"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./graphics/Graphics":44,"./graphics/GraphicsData":45,"./graphics/canvas/CanvasGraphicsRenderer":46,"./graphics/webgl/GraphicsRenderer":48,"./math":61,"./renderers/canvas/CanvasRenderer":68,"./renderers/canvas/utils/CanvasRenderTarget":70,"./renderers/webgl/WebGLRenderer":74,"./renderers/webgl/filters/Filter":76,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":79,"./renderers/webgl/managers/WebGLManager":83,"./renderers/webgl/utils/ObjectRenderer":84,"./renderers/webgl/utils/RenderTarget":86,"./sprites/Sprite":89,"./sprites/canvas/CanvasSpriteRenderer":90,"./sprites/webgl/SpriteRenderer":92,"./text/Text":94,"./textures/BaseRenderTexture":95,"./textures/BaseTexture":96,"./textures/RenderTexture":97,"./textures/Texture":98,"./textures/TextureUvs":99,"./textures/VideoBaseTexture":100,"./ticker":102,"./utils":104,"pixi-gl-core":14}],58:[function(require,module,exports){ +},{"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./graphics/Graphics":44,"./graphics/GraphicsData":45,"./graphics/canvas/CanvasGraphicsRenderer":46,"./graphics/webgl/GraphicsRenderer":48,"./math":61,"./renderers/canvas/CanvasRenderer":68,"./renderers/canvas/utils/CanvasRenderTarget":70,"./renderers/webgl/WebGLRenderer":74,"./renderers/webgl/filters/Filter":76,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":79,"./renderers/webgl/managers/WebGLManager":83,"./renderers/webgl/utils/ObjectRenderer":84,"./renderers/webgl/utils/RenderTarget":86,"./sprites/Sprite":89,"./sprites/canvas/CanvasSpriteRenderer":90,"./sprites/webgl/SpriteRenderer":92,"./text/Text":94,"./textures/BaseRenderTexture":95,"./textures/BaseTexture":96,"./textures/RenderTexture":97,"./textures/Texture":98,"./textures/TextureUvs":99,"./textures/VideoBaseTexture":100,"./ticker":102,"./utils":104,"pixi-gl-core":1}],58:[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]; @@ -13846,7 +13886,7 @@ this._lastObjectRendered = null; }; -},{"../const":40,"../display/Container":41,"../math":61,"../textures/RenderTexture":97,"../utils":104,"eventemitter3":12}],68:[function(require,module,exports){ +},{"../const":40,"../display/Container":41,"../math":61,"../textures/RenderTexture":97,"../utils":104,"eventemitter3":27}],68:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), CanvasMaskManager = require('./utils/CanvasMaskManager'), CanvasRenderTarget = require('./utils/CanvasRenderTarget'), @@ -14535,8 +14575,33 @@ this._managedTextures.push(texture); - //TODO check is power of two.. - glTexture.enableWrapClamp(); + + + + if(texture.isPowerOfTwo) + { + if(texture.mipmap) + { + glTexture.enableMipmap(); + } + + if(texture.wrapMode === CONST.WRAP_MODES.CLAMP) + { + glTexture.enableWrapClamp(); + } + else if(texture.wrapMode === CONST.WRAP_MODES.REPEAT) + { + glTexture.enableWrapRepeat(); + } + else + { + glTexture.enableWrapMirrorRepeat(); + } + } + else + { + glTexture.enableWrapClamp(); + } if(texture.scaleMode === CONST.SCALE_MODES.NEAREST) { @@ -14546,6 +14611,8 @@ { glTexture.enableLinearScaling(); } + + } if(isRenderTexture) @@ -14619,7 +14686,7 @@ module.exports = TextureManager; -},{"../../const":40,"../../utils":104,"./utils/RenderTarget":86,"pixi-gl-core":14}],74:[function(require,module,exports){ +},{"../../const":40,"../../utils":104,"./utils/RenderTarget":86,"pixi-gl-core":1}],74:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), @@ -14713,7 +14780,8 @@ * * @member {PIXI.ObjectRenderer} */ - this.currentRenderer = new ObjectRenderer(this); + this.emptyRenderer = new ObjectRenderer(this); + this.currentRenderer = this.emptyRenderer; this.initPlugins(); @@ -14849,6 +14917,16 @@ }; /** + * This shoudl be called if you wish to do some custom rendering + * It will basically render anything that may be batched up such as sprites + * + */ +WebGLRenderer.prototype.flush = function () +{ + this.setObjectRenderer(this.emptyRenderer) +} + +/** * Resizes the webGL view to the specified width and height. * * @param width {number} the new width of the webGL view @@ -15064,7 +15142,7 @@ // this = null; }; -},{"../../const":40,"../../utils":104,"../SystemRenderer":67,"./TextureManager":73,"./WebGLState":75,"./managers/FilterManager":80,"./managers/MaskManager":81,"./managers/StencilManager":82,"./utils/ObjectRenderer":84,"./utils/RenderTarget":86,"./utils/mapWebGLDrawModesToPixi":88,"pixi-gl-core":14}],75:[function(require,module,exports){ +},{"../../const":40,"../../utils":104,"../SystemRenderer":67,"./TextureManager":73,"./WebGLState":75,"./managers/FilterManager":80,"./managers/MaskManager":81,"./managers/StencilManager":82,"./utils/ObjectRenderer":84,"./utils/RenderTarget":86,"./utils/mapWebGLDrawModesToPixi":88,"pixi-gl-core":1}],75:[function(require,module,exports){ var mapWebGLBlendModesToPixi = require('./utils/mapWebGLBlendModesToPixi'); @@ -15388,7 +15466,7 @@ '}' ].join('\n'); -},{"../../../math":61,"./extractUniformsFromSrc":77,"pixi-gl-core":14}],77:[function(require,module,exports){ +},{"../../../math":61,"./extractUniformsFromSrc":77,"pixi-gl-core":1}],77:[function(require,module,exports){ var defaultValue = require('pixi-gl-core/lib/shader/defaultValue'); var mapSize = require('pixi-gl-core/lib/shader/mapSize'); @@ -15450,7 +15528,7 @@ } module.exports = extractUniformsFromSrc; -},{"pixi-gl-core/lib/shader/defaultValue":23,"pixi-gl-core/lib/shader/mapSize":27}],78:[function(require,module,exports){ +},{"pixi-gl-core/lib/shader/defaultValue":10,"pixi-gl-core/lib/shader/mapSize":14}],78:[function(require,module,exports){ var math = require('../../../math'); /* @@ -15612,7 +15690,7 @@ }; }).call(this,"/src/core/renderers/webgl/filters/spriteMask") -},{"../../../../math":61,"../Filter":76,"fs":3}],80:[function(require,module,exports){ +},{"../../../../math":61,"../Filter":76,"fs":18}],80:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), RenderTarget = require('../utils/RenderTarget'), @@ -15963,7 +16041,7 @@ FilterManager.pool = {} -},{"../../../const":40,"../../../math":61,"../../../utils":104,"../filters/filterTransforms":78,"../utils/Quad":85,"../utils/RenderTarget":86,"./WebGLManager":83,"bit-twiddle":2,"pixi-gl-core":14}],81:[function(require,module,exports){ +},{"../../../const":40,"../../../math":61,"../../../utils":104,"../filters/filterTransforms":78,"../utils/Quad":85,"../utils/RenderTarget":86,"./WebGLManager":83,"bit-twiddle":17,"pixi-gl-core":1}],81:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), AlphaMaskFilter = require('../filters/spriteMask/SpriteMaskFilter'); @@ -16521,7 +16599,7 @@ -},{"../../../utils/createIndicesForQuads":103,"pixi-gl-core":14}],86:[function(require,module,exports){ +},{"../../../utils/createIndicesForQuads":103,"pixi-gl-core":1}],86:[function(require,module,exports){ var math = require('../../../math'), utils = require('../../../utils'), CONST = require('../../../const'), @@ -16842,7 +16920,7 @@ this.texture = null; }; -},{"../../../const":40,"../../../math":61,"../../../utils":104,"pixi-gl-core":14}],87:[function(require,module,exports){ +},{"../../../const":40,"../../../math":61,"../../../utils":104,"pixi-gl-core":1}],87:[function(require,module,exports){ CONST = require('../../../const'); /** @@ -18167,13 +18245,13 @@ this.colors = null; } -},{"../../const":40,"../../renderers/webgl/WebGLRenderer":74,"../../renderers/webgl/utils/ObjectRenderer":84,"../../utils/createIndicesForQuads":103,"./generateMultiTextureShader":93,"bit-twiddle":2,"pixi-gl-core":14}],93:[function(require,module,exports){ +},{"../../const":40,"../../renderers/webgl/WebGLRenderer":74,"../../renderers/webgl/utils/ObjectRenderer":84,"../../utils/createIndicesForQuads":103,"./generateMultiTextureShader":93,"bit-twiddle":17,"pixi-gl-core":1}],93:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; function generateMultiTextureShader(gl, maxTextures) { - var vertexSrc = "precision lowp float;\n#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vTextureId = aTextureId;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}"; + var vertexSrc = "#define GLSLIFY 1\nprecision lowp float;\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vTextureId = aTextureId;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}"; var fragmentSrc = fragTemplate fragmentSrc = fragmentSrc.replace(/\%count\%/gi, maxTextures); @@ -18232,7 +18310,7 @@ module.exports = generateMultiTextureShader; -},{"pixi-gl-core":14}],94:[function(require,module,exports){ +},{"pixi-gl-core":1}],94:[function(require,module,exports){ var Sprite = require('../sprites/Sprite'), Texture = require('../textures/Texture'), math = require('../math'), @@ -19144,7 +19222,8 @@ },{"../const":40,"../math":61,"../renderers/webgl/managers/FilterManager":80,"../renderers/webgl/utils/RenderTarget":86,"./BaseTexture":96,"./Texture":98}],96:[function(require,module,exports){ var utils = require('../utils'), CONST = require('../const'), - EventEmitter = require('eventemitter3'); + EventEmitter = require('eventemitter3'), + bitTwiddle = require('bit-twiddle'); /** * A texture stores the information that represents an image. All textures have a base texture. @@ -19272,7 +19351,17 @@ * * @member {boolean} */ - this.mipmap = false; + this.mipmap = CONST.MIPMAP_TEXTURES; + + + /** + * + * Set this to true if a mipmap of this texture needs to be generated. This value needs to be set before the texture is used + * Also the texture must be a power of two size to work + * + * @member {boolean} + */ + this.wrap = CONST.MIPMAP_TEXTURES; /** * A map of renderer IDs to webgl textures @@ -19324,7 +19413,7 @@ this.width = this.realWidth / this.resolution; this.height = this.realHeight / this.resolution; - this.isPowerOfTwo = utils.isPowerOfTwo(this.realWidth, this.realHeight); + this.isPowerOfTwo = bitTwiddle.isPow2(this.realWidth) && bitTwiddle.isPow2(this.realHeight); this.emit('update', this); }; @@ -19579,7 +19668,7 @@ return baseTexture; }; -},{"../const":40,"../utils":104,"eventemitter3":12}],97:[function(require,module,exports){ +},{"../const":40,"../utils":104,"bit-twiddle":17,"eventemitter3":27}],97:[function(require,module,exports){ var BaseRenderTexture = require('./BaseRenderTexture'), Texture = require('./Texture'), math = require('../math'), @@ -20130,7 +20219,7 @@ */ Texture.EMPTY = new Texture(new BaseTexture()); -},{"../math":61,"../utils":104,"./BaseTexture":96,"./TextureUvs":99,"./VideoBaseTexture":100,"eventemitter3":12}],99:[function(require,module,exports){ +},{"../math":61,"../utils":104,"./BaseTexture":96,"./TextureUvs":99,"./VideoBaseTexture":100,"eventemitter3":27}],99:[function(require,module,exports){ /** * A standard object to store the Uvs of a texture @@ -20815,7 +20904,7 @@ module.exports = Ticker; -},{"../const":40,"eventemitter3":12}],102:[function(require,module,exports){ +},{"../const":40,"eventemitter3":27}],102:[function(require,module,exports){ var Ticker = require('./Ticker'); /** @@ -20971,46 +21060,6 @@ return ((rgb[0]*255 << 16) + (rgb[1]*255 << 8) + rgb[2]*255); }, - - - /** - * Given a number, this function returns the closest number that is a power of two - * this function is taken from Starling Framework as its pretty neat ;) - * - * @param number {number} - * @return {number} the closest number that is a power of two - */ - getNextPowerOfTwo: function (number) - { - // see: http://en.wikipedia.org/wiki/Power_of_two#Fast_algorithm_to_check_if_a_positive_number_is_a_power_of_two - if (number > 0 && (number & (number - 1)) === 0) - { - return number; - } - else - { - var result = 1; - - while (result < number) - { - result <<= 1; - } - - return result; - } - }, - - /** - * checks if the given width and height make a power of two rectangle - * - * @param width {number} - * @param height {number} - * @return {boolean} - */ - isPowerOfTwo: function (width, height) - { - return (width > 0 && (width & (width - 1)) === 0 && height > 0 && (height & (height - 1)) === 0); - }, /** * get the resolution of an asset by looking for the prefix @@ -21148,7 +21197,7 @@ BaseTextureCache: {} }; -},{"../const":40,"./pluginTarget":105,"async":1,"eventemitter3":12}],105:[function(require,module,exports){ +},{"../const":40,"./pluginTarget":105,"async":16,"eventemitter3":27}],105:[function(require,module,exports){ /** * Mixins functionality to make an object have "plugins". * @@ -23576,9 +23625,9 @@ { core.Filter.call(this, // vertex shader - "precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", + "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform float m[20];\n\nvoid main(void)\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n gl_FragColor.r += (m[1] * c.g);\n gl_FragColor.r += (m[2] * c.b);\n gl_FragColor.r += (m[3] * c.a);\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n gl_FragColor.g += (m[6] * c.g);\n gl_FragColor.g += (m[7] * c.b);\n gl_FragColor.g += (m[8] * c.a);\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n gl_FragColor.b += (m[11] * c.g);\n gl_FragColor.b += (m[12] * c.b);\n gl_FragColor.b += (m[13] * c.a);\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n gl_FragColor.a += (m[16] * c.g);\n gl_FragColor.a += (m[17] * c.b);\n gl_FragColor.a += (m[18] * c.a);\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform float m[20];\n\nvoid main(void)\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n gl_FragColor.r += (m[1] * c.g);\n gl_FragColor.r += (m[2] * c.b);\n gl_FragColor.r += (m[3] * c.a);\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n gl_FragColor.g += (m[6] * c.g);\n gl_FragColor.g += (m[7] * c.b);\n gl_FragColor.g += (m[8] * c.a);\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n gl_FragColor.b += (m[11] * c.g);\n gl_FragColor.b += (m[12] * c.b);\n gl_FragColor.b += (m[13] * c.a);\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n gl_FragColor.a += (m[16] * c.g);\n gl_FragColor.a += (m[17] * c.b);\n gl_FragColor.a += (m[18] * c.a);\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\n}\n" ); this.uniforms.m = [ @@ -24109,7 +24158,7 @@ // vertex shader "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMapCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n}\n" ); @@ -24181,9 +24230,9 @@ { core.Filter.call(this, // vertex shader - "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", + "#define GLSLIFY 1\nprecision lowp float;\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float gray;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float gray;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n}\n" ); this.uniforms.gray = 1; @@ -24272,7 +24321,7 @@ "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}\n\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n{\n coord *= filterArea.xy;\n coord += filterArea.zw;\n\n return coord;\n}\n\nvec2 unmapCoord( vec2 coord )\n{\n coord -= filterArea.zw;\n coord /= filterArea.xy;\n\n return coord;\n}\n\nvec2 twist(vec2 coord)\n{\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratioDist = (radius - dist) / radius;\n float angleMod = ratioDist * ratioDist * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n coord += offset;\n\n return coord;\n}\n\nvoid main(void)\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n{\n coord *= filterArea.xy;\n coord += filterArea.zw;\n\n return coord;\n}\n\nvec2 unmapCoord( vec2 coord )\n{\n coord -= filterArea.zw;\n coord /= filterArea.xy;\n\n return coord;\n}\n\nvec2 twist(vec2 coord)\n{\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratioDist = (radius - dist) / radius;\n float angleMod = ratioDist * ratioDist * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n coord += offset;\n\n return coord;\n}\n\nvoid main(void)\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n" ); this.uniforms.radius = 400; @@ -24367,7 +24416,8 @@ core.filters = require('./filters'); core.interaction = require('./interaction'); core.loaders = require('./loaders'); -//core.mesh = require('./mesh'); +core.mesh = require('./mesh'); +core.particles = require('./particles'); core.accessibility = require('./accessibility'); // export a premade loader instance @@ -24387,7 +24437,7 @@ global.PIXI = core; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./accessibility":38,"./core":57,"./deprecation":106,"./extras":113,"./filters":123,"./interaction":128,"./loaders":131,"./polyfill":137}],126:[function(require,module,exports){ +},{"./accessibility":38,"./core":57,"./deprecation":106,"./extras":113,"./filters":123,"./interaction":128,"./loaders":131,"./mesh":138,"./particles":141,"./polyfill":147}],126:[function(require,module,exports){ var core = require('../core'); /** @@ -25529,7 +25579,7 @@ }; }; -},{"../core":57,"../extras":113,"path":4,"resource-loader":33}],131:[function(require,module,exports){ +},{"../core":57,"../extras":113,"path":19,"resource-loader":33}],131:[function(require,module,exports){ /** * @file Main export of the PIXI loaders library * @author Mat Groves @@ -25684,7 +25734,7 @@ }; }; -},{"../core":57,"path":4,"resource-loader":33}],134:[function(require,module,exports){ +},{"../core":57,"path":19,"resource-loader":33}],134:[function(require,module,exports){ var core = require('../core'); module.exports = function () @@ -25707,6 +25757,2013 @@ }; },{"../core":57}],135:[function(require,module,exports){ +var core = require('../core'), + glCore = require('pixi-gl-core'), + Shader = require('./webgl/MeshShader'), + tempPoint = new core.Point(), + tempPolygon = new core.Polygon(); + +/** + * Base mesh class + * @class + * @extends PIXI.Container + * @memberof PIXI.mesh + * @param texture {PIXI.Texture} The texture to use + * @param [vertices] {Float32Array} if you want to specify the vertices + * @param [uvs] {Float32Array} if you want to specify the uvs + * @param [indices] {Uint16Array} if you want to specify the indices + * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts + */ +function Mesh(texture, vertices, uvs, indices, drawMode) +{ + core.Container.call(this); + + /** + * The texture of the Mesh + * + * @member {PIXI.Texture} + * @private + */ + this._texture = null; + + /** + * The Uvs of the Mesh + * + * @member {Float32Array} + */ + this.uvs = uvs || new Float32Array([0, 0, + 1, 0, + 1, 1, + 0, 1]); + + /** + * An array of vertices + * + * @member {Float32Array} + */ + this.vertices = vertices || new Float32Array([0, 0, + 100, 0, + 100, 100, + 0, 100]); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + // TODO auto generate this based on draw mode! + this.indices = indices || new Uint16Array([0, 1, 3, 2]); + + /** + * Whether the Mesh is dirty or not + * + * @member {boolean} + */ + this.dirty = true; + + /** + * The blend mode to be applied to the sprite. Set to `PIXI.BLEND_MODES.NORMAL` to remove any blend mode. + * + * @member {number} + * @default PIXI.BLEND_MODES.NORMAL + * @see PIXI.BLEND_MODES + */ + this.blendMode = core.BLEND_MODES.NORMAL; + + /** + * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. + * + * @member {number} + */ + this.canvasPadding = 0; + + /** + * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts + * + * @member {number} + * @see PIXI.mesh.Mesh.DRAW_MODES + */ + this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; + + // run texture setter; + this.texture = texture; + + /** + * The default shader that is used if a mesh doesn't have a more specific one. + * + * @member {PIXI.Shader} + */ + this.shader = null; + + this._glDatas = []; +} + +// constructor +Mesh.prototype = Object.create(core.Container.prototype); +Mesh.prototype.constructor = Mesh; +module.exports = Mesh; + +Object.defineProperties(Mesh.prototype, { + /** + * The texture that the sprite is using + * + * @member {PIXI.Texture} + * @memberof PIXI.mesh.Mesh# + */ + texture: { + get: function () + { + return this._texture; + }, + set: function (value) + { + if (this._texture === value) + { + return; + } + + this._texture = value; + + if (value) + { + // wait for the texture to load + if (value.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + value.once('update', this._onTextureUpdate, this); + } + } + } + } +}); + +/** + * Renders the object using the WebGL renderer + * + * @param renderer {PIXI.WebGLRenderer} a reference to the WebGL renderer + * @private + */ +Mesh.prototype._renderWebGL = function (renderer) +{ + // get rid of any thing that may be batching. + renderer.flush(); + + // renderer.plugins.mesh.render(this); + var gl = renderer.gl; + var glData = this._glDatas[renderer.CONTEXT_UID]; + + if(!glData) + { + glData = { + shader:new Shader(gl), + vertexBuffer:glCore.GLBuffer.createVertexBuffer(gl, this.vertices, gl.STREAM_DRAW), + uvBuffer:glCore.GLBuffer.createVertexBuffer(gl, this.uvs, gl.STREAM_DRAW), + indexBuffer:glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW), + // build the vao object that will render.. + vao:new glCore.VertexArrayObject(gl) + } + + // build the vao object that will render.. + glData.vao = new glCore.VertexArrayObject(gl) + .addIndex(glData.indexBuffer) + .addAttribute(glData.vertexBuffer, glData.shader.attributes.aVertexPosition, gl.FLOAT, false, 2 * 4, 0) + .addAttribute(glData.uvBuffer, glData.shader.attributes.aTextureCoord, gl.FLOAT, false, 2 * 4, 0) + + this._glDatas[renderer.CONTEXT_UID] = glData; + } + + if(this.dirty) + { + this.dirty = false; + glData.uvBuffer.upload(); + } + + glData.vertexBuffer.upload(); + + renderer.bindShader(glData.shader); + renderer.bindTexture(this._texture, 0); + + glData.shader.uniforms.translationMatrix = this.worldTransform.toArray(true); + glData.shader.uniforms.alpha = this.worldAlpha; + + var drawMode = this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH ? gl.TRIANGLE_STRIP : gl.TRIANGLES; + + + glData.vao.bind() + .draw(drawMode, this.indices.length) + .unbind(); +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {PIXI.CanvasRenderer} + * @private + */ +Mesh.prototype._renderCanvas = function (renderer) +{ + var context = renderer.context; + + var transform = this.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); + } + else + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); + } + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) + { + this._renderCanvasTriangleMesh(context); + } + else + { + this._renderCanvasTriangles(context); + } +}; + +/** + * Draws the object in Triangle Mesh mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangleMesh = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + + var length = vertices.length / 2; + // this.count++; + + for (var i = 0; i < length - 2; i++) + { + // draw some triangles! + var index = i * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); + } +}; + +/** + * Draws the object in triangle mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangles = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + var indices = this.indices; + + var length = indices.length; + // this.count++; + + for (var i = 0; i < length; i += 3) + { + // draw some triangles! + var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); + } +}; + +/** + * Draws one of the triangles that form this Mesh + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @param vertices {Float32Array} a reference to the vertices of the Mesh + * @param uvs {Float32Array} a reference to the uvs of the Mesh + * @param index0 {number} the index of the first vertex + * @param index1 {number} the index of the second vertex + * @param index2 {number} the index of the third vertex + * @private + */ +Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) +{ + var textureSource = this._texture.baseTexture.source; + var textureWidth = this._texture.baseTexture.width; + var textureHeight = this._texture.baseTexture.height; + + var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; + var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; + + var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; + var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; + + if (this.canvasPadding > 0) + { + var paddingX = this.canvasPadding / this.worldTransform.a; + var paddingY = this.canvasPadding / this.worldTransform.d; + var centerX = (x0 + x1 + x2) / 3; + var centerY = (y0 + y1 + y2) / 3; + + var normX = x0 - centerX; + var normY = y0 - centerY; + + var dist = Math.sqrt(normX * normX + normY * normY); + x0 = centerX + (normX / dist) * (dist + paddingX); + y0 = centerY + (normY / dist) * (dist + paddingY); + + // + + normX = x1 - centerX; + normY = y1 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x1 = centerX + (normX / dist) * (dist + paddingX); + y1 = centerY + (normY / dist) * (dist + paddingY); + + normX = x2 - centerX; + normY = y2 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x2 = centerX + (normX / dist) * (dist + paddingX); + y2 = centerY + (normY / dist) * (dist + paddingY); + } + + context.save(); + context.beginPath(); + + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + context.closePath(); + + context.clip(); + + // Compute matrix transform + var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); + var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); + var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); + var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); + var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); + var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); + var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); + + context.transform(deltaA / delta, deltaD / delta, + deltaB / delta, deltaE / delta, + deltaC / delta, deltaF / delta); + + context.drawImage(textureSource, 0, 0); + context.restore(); +}; + + + +/** + * Renders a flat Mesh + * + * @param Mesh {PIXI.mesh.Mesh} The Mesh to render + * @private + */ +Mesh.prototype.renderMeshFlat = function (Mesh) +{ + var context = this.context; + var vertices = Mesh.vertices; + + var length = vertices.length/2; + // this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + // draw some triangles! + var index = i*2; + + var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; + var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + } + + context.fillStyle = '#FF0000'; + context.fill(); + context.closePath(); +}; + +/** + * When the texture is updated, this event will fire to update the scale and frame + * + * @param event + * @private + */ +Mesh.prototype._onTextureUpdate = function () +{ + this.updateFrame = true; +}; + +/** + * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. + * + * @param matrix {PIXI.Matrix} the transformation matrix of the sprite + * @return {PIXI.Rectangle} the framing rectangle + */ +Mesh.prototype.getBounds = function (matrix) +{ + if (!this._currentBounds) { + var worldTransform = matrix || this.worldTransform; + + var a = worldTransform.a; + var b = worldTransform.b; + var c = worldTransform.c; + var d = worldTransform.d; + var tx = worldTransform.tx; + var ty = worldTransform.ty; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + var vertices = this.vertices; + for (var i = 0, n = vertices.length; i < n; i += 2) { + var rawX = vertices[i], rawY = vertices[i + 1]; + var x = (a * rawX) + (c * rawY) + tx; + var y = (d * rawY) + (b * rawX) + ty; + + minX = x < minX ? x : minX; + minY = y < minY ? y : minY; + + maxX = x > maxX ? x : maxX; + maxY = y > maxY ? y : maxY; + } + + if (minX === -Infinity || maxY === Infinity) { + return core.Rectangle.EMPTY; + } + + var bounds = this._bounds; + + bounds.x = minX; + bounds.width = maxX - minX; + + bounds.y = minY; + bounds.height = maxY - minY; + + // store a reference so that if this function gets called again in the render cycle we do not have to recalculate + this._currentBounds = bounds; + } + + return this._currentBounds; +}; + +/** + * Tests if a point is inside this mesh. Works only for TRIANGLE_MESH + * + * @param point {PIXI.Point} the point to test + * @return {boolean} the result of the test + */ +Mesh.prototype.containsPoint = function( point ) { + if (!this.getBounds().contains(point.x, point.y)) { + return false; + } + this.worldTransform.applyInverse(point, tempPoint); + + var vertices = this.vertices; + var points = tempPolygon.points; + var i, len; + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLES) { + var indices = this.indices; + len = this.indices.length; + //TODO: inline this. + for (i=0;i 1) + { + ratio = 1; + } + + perpLength = Math.sqrt(perpX * perpX + perpY * perpY); + num = this._texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + perpX /= perpLength; + perpY /= perpLength; + + perpX *= num; + perpY *= num; + + vertices[index] = point.x + perpX; + vertices[index+1] = point.y + perpY; + vertices[index+2] = point.x - perpX; + vertices[index+3] = point.y - perpY; + + lastPoint = point; + } + + this.containerUpdateTransform(); +}; + +},{"../core":57,"./Mesh":135}],138:[function(require,module,exports){ +/** + * @file Main export of the PIXI extras library + * @author Mat Groves + * @copyright 2013-2015 GoodBoyDigital + * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License} + */ + +/** + * @namespace PIXI.mesh + */ +module.exports = { + Mesh: require('./Mesh'), + Plane: require('./Plane'), + Rope: require('./Rope'), + MeshShader: require('./webgl/MeshShader') +}; + +},{"./Mesh":135,"./Plane":136,"./Rope":137,"./webgl/MeshShader":139}],139:[function(require,module,exports){ +var Shader = require('pixi-gl-core').GLShader; + +/** + * @class + * @extends PIXI.Shader + * @memberof PIXI.mesh + * @param shaderManager {PIXI.ShaderManager} The WebGL shader manager this shader works for. + */ +function MeshShader(gl) +{ + Shader.call(this, + gl, + // vertex shader + [ + 'precision lowp float;', + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + + 'uniform mat3 translationMatrix;', + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + + 'void main(void){', + ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + ' vTextureCoord = aTextureCoord;', + '}' + ].join('\n'), + [ + 'precision lowp float;', + + 'varying vec2 vTextureCoord;', + 'uniform float alpha;', + + 'uniform sampler2D uSampler;', + + 'void main(void){', + ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', + // ' gl_FragColor = vec4(1.0);', + '}' + ].join('\n') + ); +} + +MeshShader.prototype = Object.create(Shader.prototype); +MeshShader.prototype.constructor = MeshShader; +module.exports = MeshShader; + + +},{"pixi-gl-core":1}],140:[function(require,module,exports){ +var core = require('../core'); + +/** + * The ParticleContainer class is a really fast version of the Container built solely for speed, + * so use when you need a lot of sprites or particles. The tradeoff of the ParticleContainer is that advanced + * functionality will not work. ParticleContainer implements only the basic object transform (position, scale, rotation). + * Any other functionality like tinting, masking, etc will not work on sprites in this batch. + * + * It's extremely easy to use : + * + * ```js + * var container = new ParticleContainer(); + * + * for (var i = 0; i < 100; ++i) + * { + * var sprite = new PIXI.Sprite.fromImage("myImage.png"); + * container.addChild(sprite); + * } + * ``` + * + * And here you have a hundred sprites that will be renderer at the speed of light. + * + * @class + * @extends PIXI.Container + * @memberof PIXI + * @param [maxSize=15000] {number} The maximum number of particles that can be renderer by the container. + * @param [properties] {object} The properties of children that should be uploaded to the gpu and applied. + * @param [properties.scale=false] {boolean} When true, scale be uploaded and applied. + * @param [properties.position=true] {boolean} When true, position be uploaded and applied. + * @param [properties.rotation=false] {boolean} When true, rotation be uploaded and applied. + * @param [properties.uvs=false] {boolean} When true, uvs be uploaded and applied. + * @param [properties.alpha=false] {boolean} When true, alpha be uploaded and applied. + * @param [batchSize=15000] {number} Number of particles per batch. + */ +function ParticleContainer(maxSize, properties, batchSize) +{ + core.Container.call(this); + + batchSize = batchSize || 15000; //CONST.SPRITE_BATCH_SIZE; // 2000 is a nice balance between mobile / desktop + maxSize = maxSize || 15000; + + // Making sure the batch size is valid + // 65535 is max vertex index in the index buffer (see ParticleRenderer) + // so max number of particles is 65536 / 4 = 16384 + var maxBatchSize = 16384; + if (batchSize > maxBatchSize) { + batchSize = maxBatchSize; + } + + if (batchSize > maxSize) { + batchSize = maxSize; + } + + /** + * Set properties to be dynamic (true) / static (false) + * + * @member {boolean[]} + * @private + */ + this._properties = [false, true, false, false, false]; + + /** + * @member {number} + * @private + */ + this._maxSize = maxSize; + + /** + * @member {number} + * @private + */ + this._batchSize = batchSize; + + /** + * @member {WebGLBuffer} + * @private + */ + this._glBuffers = []; + + /** + * @member {number} + * @private + */ + this._bufferToUpdate = 0; + + /** + * @member {boolean} + * + */ + this.interactiveChildren = false; + + /** + * The blend mode to be applied to the sprite. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode. + * + * @member {number} + * @default PIXI.BLEND_MODES.NORMAL + * @see PIXI.BLEND_MODES + */ + this.blendMode = core.BLEND_MODES.NORMAL; + + /** + * Used for canvas renderering. If true then the elements will be positioned at the nearest pixel. This provides a nice speed boost. + * + * @member {boolean} + * @default true; + */ + this.roundPixels = true; + + this.baseTexture = null; + + this.setProperties(properties); +} + +ParticleContainer.prototype = Object.create(core.Container.prototype); +ParticleContainer.prototype.constructor = ParticleContainer; +module.exports = ParticleContainer; + +/** + * Sets the private properties array to dynamic / static based on the passed properties object + * + * @param properties {object} The properties to be uploaded + */ +ParticleContainer.prototype.setProperties = function(properties) +{ + if ( properties ) { + this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; + this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; + this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; + this._properties[4] = 'alpha' in properties ? !!properties.alpha : this._properties[4]; + } +}; + +/** + * Updates the object transform for rendering + * + * @private + */ +ParticleContainer.prototype.updateTransform = function () +{ + + // TODO don't need to! + this.displayObjectUpdateTransform(); + // PIXI.Container.prototype.updateTransform.call( this ); +}; + +/** + * Renders the container using the WebGL renderer + * + * @param renderer {PIXI.WebGLRenderer} The webgl renderer + * @private + */ +ParticleContainer.prototype.renderWebGL = function (renderer) +{ + if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable) + { + return; + } + + + if(!this.baseTexture) + { + this.baseTexture = this.children[0]._texture.baseTexture; + if(!this.baseTexture.hasLoaded) + { + this.baseTexture.once('update', function(){ + this.onChildrenChange(0); + }, this) + } + } + + + renderer.setObjectRenderer( renderer.plugins.particle ); + renderer.plugins.particle.render( this ); +}; + +/** + * Set the flag that static data should be updated to true + * + * @private + */ +ParticleContainer.prototype.onChildrenChange = function (smallestChildIndex) +{ + var bufferIndex = Math.floor(smallestChildIndex / this._batchSize); + if (bufferIndex < this._bufferToUpdate) { + this._bufferToUpdate = bufferIndex; + } +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {PIXI.CanvasRenderer} The canvas renderer + * @private + */ +ParticleContainer.prototype.renderCanvas = function (renderer) +{ + if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable) + { + return; + } + + var context = renderer.context; + var transform = this.worldTransform; + var isRotated = true; + + var positionX = 0; + var positionY = 0; + + var finalWidth = 0; + var finalHeight = 0; + + var compositeOperation = renderer.blendModes[this.blendMode]; + if (compositeOperation !== context.globalCompositeOperation) + { + context.globalCompositeOperation = compositeOperation; + } + + context.globalAlpha = this.worldAlpha; + + this.displayObjectUpdateTransform(); + + for (var i = 0; i < this.children.length; ++i) + { + var child = this.children[i]; + + if (!child.visible) + { + continue; + } + + var frame = child.texture.frame; + + context.globalAlpha = this.worldAlpha * child.alpha; + + if (child.rotation % (Math.PI * 2) === 0) + { + // this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call + if (isRotated) + { + context.setTransform( + transform.a, + transform.b, + transform.c, + transform.d, + transform.tx, + transform.ty + ); + + isRotated = false; + } + + positionX = ((child.anchor.x) * (-frame.width * child.scale.x) + child.position.x + 0.5); + positionY = ((child.anchor.y) * (-frame.height * child.scale.y) + child.position.y + 0.5); + + finalWidth = frame.width * child.scale.x; + finalHeight = frame.height * child.scale.y; + + } + else + { + if (!isRotated) + { + isRotated = true; + } + + child.displayObjectUpdateTransform(); + + var childTransform = child.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform( + childTransform.a, + childTransform.b, + childTransform.c, + childTransform.d, + childTransform.tx | 0, + childTransform.ty | 0 + ); + } + else + { + context.setTransform( + childTransform.a, + childTransform.b, + childTransform.c, + childTransform.d, + childTransform.tx, + childTransform.ty + ); + } + + positionX = ((child.anchor.x) * (-frame.width) + 0.5); + positionY = ((child.anchor.y) * (-frame.height) + 0.5); + + finalWidth = frame.width; + finalHeight = frame.height; + } + + context.drawImage( + child.texture.baseTexture.source, + frame.x, + frame.y, + frame.width, + frame.height, + positionX, + positionY, + finalWidth, + finalHeight + ); + } +}; + +/** + * Destroys the container + * + * @param [destroyChildren=false] {boolean} if set to true, all the children will have their destroy method called as well + */ +ParticleContainer.prototype.destroy = function () { + Container.prototype.destroy.apply(this, arguments); + + if (this._buffers) { + for (var i = 0; i < this._buffers.length; ++i) { + this._buffers[i].destroy(); + } + } + + this._properties = null; + this._buffers = null; +}; + +},{"../core":57}],141:[function(require,module,exports){ +/** + * @file Main export of the PIXI extras library + * @author Mat Groves + * @copyright 2013-2015 GoodBoyDigital + * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License} + */ + +/** + * @namespace PIXI.mesh + */ +module.exports = { + ParticleContainer: require('./ParticleContainer'), + ParticleRenderer: require('./webgl/ParticleRenderer') +}; + +},{"./ParticleContainer":140,"./webgl/ParticleRenderer":143}],142:[function(require,module,exports){ +var glCore = require('pixi-gl-core'), + createIndicesForQuads = require('../../core/utils/createIndicesForQuads'); + +/** + * @author Mat Groves + * + * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ + * for creating the original pixi version! + * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer + * + * Heavily inspired by LibGDX's ParticleBuffer: + * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleBuffer.java + */ + +/** + * The particle buffer manages the static and dynamic buffers for a particle container. + * + * @class + * @private + * @memberof PIXI + */ +function ParticleBuffer(gl, properties, dynamicPropertyFlags, size) +{ + /** + * The current WebGL drawing context. + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * Size of a single vertex. + * + * @member {number} + */ + this.vertSize = 2; + + /** + * Size of a single vertex in bytes. + * + * @member {number} + */ + this.vertByteSize = this.vertSize * 4; + + /** + * The number of particles the buffer can hold + * + * @member {number} + */ + this.size = size; + + /** + * A list of the properties that are dynamic. + * + * @member {object[]} + */ + this.dynamicProperties = []; + + /** + * A list of the properties that are static. + * + * @member {object[]} + */ + this.staticProperties = []; + + for (var i = 0; i < properties.length; i++) + { + var property = properties[i]; + + if(dynamicPropertyFlags[i]) + { + this.dynamicProperties.push(property); + } + else + { + this.staticProperties.push(property); + } + } + + this.staticStride = 0; + this.staticBuffer = null; + this.staticData = null; + + this.dynamicStride = 0; + this.dynamicBuffer = null; + this.dynamicData = null; + + this.initBuffers(); + +} + +ParticleBuffer.prototype.constructor = ParticleBuffer; +module.exports = ParticleBuffer; + +/** + * Sets up the renderer context and necessary buffers. + * + * @private + */ +ParticleBuffer.prototype.initBuffers = function () +{ + var gl = this.gl; + var i; + var property; + + var dynamicOffset = 0; + + + /** + * Holds the indices of the geometry (quads) to draw + * + * @member {Uint16Array} + */ + this.indices = createIndicesForQuads(this.size) + this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); + + + this.dynamicStride = 0; + + for (i = 0; i < this.dynamicProperties.length; i++) + { + property = this.dynamicProperties[i]; + + property.offset = dynamicOffset; + dynamicOffset += property.size; + this.dynamicStride += property.size; + } + + this.dynamicData = new Float32Array( this.size * this.dynamicStride * 4); + this.dynamicBuffer = glCore.GLBuffer.createVertexBuffer(gl, this.dynamicData, gl.STREAM_DRAW); + + // static // + var staticOffset = 0; + this.staticStride = 0; + + for (i = 0; i < this.staticProperties.length; i++) + { + property = this.staticProperties[i]; + + property.offset = staticOffset; + staticOffset += property.size; + this.staticStride += property.size; + + + } + + this.staticData = new Float32Array( this.size * this.staticStride * 4); + this.staticBuffer = glCore.GLBuffer.createVertexBuffer(gl, this.staticData, gl.STATIC_DRAW); + + + this.vao = new glCore.VertexArrayObject(gl) + .addIndex(this.indexBuffer); + + for (i = 0; i < this.dynamicProperties.length; i++) + { + property = this.dynamicProperties[i]; + this.vao.addAttribute(this.dynamicBuffer, property.attribute, gl.FLOAT, false, this.dynamicStride * 4, property.offset * 4); + } + + for (i = 0; i < this.staticProperties.length; i++) + { + property = this.staticProperties[i]; + this.vao.addAttribute(this.staticBuffer, property.attribute, gl.FLOAT, false, this.staticStride * 4, property.offset * 4); + } +}; + +/** + * Uploads the dynamic properties. + * + */ +ParticleBuffer.prototype.uploadDynamic = function(children, startIndex, amount) +{ + var gl = this.gl; + + for (var i = 0; i < this.dynamicProperties.length; i++) + { + var property = this.dynamicProperties[i]; + property.uploadFunction(children, startIndex, amount, this.dynamicData, this.dynamicStride, property.offset); + } + + this.dynamicBuffer.upload(); +}; + +/** + * Uploads the static properties. + * + */ +ParticleBuffer.prototype.uploadStatic = function(children, startIndex, amount) +{ + var gl = this.gl; + + for (var i = 0; i < this.staticProperties.length; i++) + { + var property = this.staticProperties[i]; + property.uploadFunction(children, startIndex, amount, this.staticData, this.staticStride, property.offset); + } + + this.staticBuffer.upload(); +}; + +/** + * Binds the buffers to the GPU + * + */ +ParticleBuffer.prototype.bind = function () +{ + var gl = this.gl; + var i, property; + + this.vao.bind(); +}; + +/** + * Destroys the ParticleBuffer. + * + */ +ParticleBuffer.prototype.destroy = function () +{ + this.dynamicProperties = null; + this.dynamicData = null; + this.dynamicBuffer.destroy(); + + this.staticProperties = null; + this.staticData = null; + this.staticBuffer.destroy(); +}; + +},{"../../core/utils/createIndicesForQuads":103,"pixi-gl-core":1}],143:[function(require,module,exports){ +var core = require('../../core'), + ParticleShader = require('./ParticleShader'), + ParticleBuffer = require('./ParticleBuffer'); + +/** + * @author Mat Groves + * + * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ + * for creating the original pixi version! + * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer + * + * Heavily inspired by LibGDX's ParticleRenderer: + * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleRenderer.java + */ + +/** + * + * @class + * @private + * @memberof PIXI + * @param renderer {PIXI.WebGLRenderer} The renderer this sprite batch works for. + */ +function ParticleRenderer(renderer) +{ + core.ObjectRenderer.call(this, renderer); + + // 65535 is max vertex index in the index buffer (see ParticleRenderer) + // so max number of particles is 65536 / 4 = 16384 + // and max number of element in the index buffer is 16384 * 6 = 98304 + // Creating a full index buffer, overhead is 98304 * 2 = 196Ko + var numIndices = 98304; + + /** + * The default shader that is used if a sprite doesn't have a more specific one. + * + * @member {PIXI.Shader} + */ + this.shader = null; + + this.indexBuffer = null; + + this.properties = null; + + this.tempMatrix = new core.math.Matrix(); + + this.CONTEXT_UID = 0; +} + +ParticleRenderer.prototype = Object.create(core.ObjectRenderer.prototype); +ParticleRenderer.prototype.constructor = ParticleRenderer; +module.exports = ParticleRenderer; + +core.WebGLRenderer.registerPlugin('particle', ParticleRenderer); + +/** + * When there is a WebGL context change + * + * @private + */ +ParticleRenderer.prototype.onContextChange = function () +{ + var gl = this.renderer.gl; + + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + // setup default shader + this.shader = new ParticleShader(gl); + + this.properties = [ + // verticesData + { + attribute:this.shader.attributes.aVertexPosition, + size:2, + uploadFunction:this.uploadVertices, + offset:0 + }, + // positionData + { + attribute:this.shader.attributes.aPositionCoord, + size:2, + uploadFunction:this.uploadPosition, + offset:0 + }, + // rotationData + { + attribute:this.shader.attributes.aRotation, + size:1, + uploadFunction:this.uploadRotation, + offset:0 + }, + // uvsData + { + attribute:this.shader.attributes.aTextureCoord, + size:2, + uploadFunction:this.uploadUvs, + offset:0 + }, + // alphaData + { + attribute:this.shader.attributes.aColor, + size:1, + uploadFunction:this.uploadAlpha, + offset:0 + } + ]; + +}; + +/** + * Starts a new particle batch. + * + */ +ParticleRenderer.prototype.start = function () +{ + this.renderer.bindShader(this.shader); +}; + + +/** + * Renders the particle container object. + * + * @param container {PIXI.ParticleContainer} The container to render using this ParticleRenderer + */ +ParticleRenderer.prototype.render = function (container) +{ + var children = container.children, + totalChildren = children.length, + maxSize = container._maxSize, + batchSize = container._batchSize; + + if(totalChildren === 0) + { + return; + } + else if(totalChildren > maxSize) + { + totalChildren = maxSize; + } + + var buffers = container._glBuffers[this.renderer.CONTEXT_UID]; + + if(!buffers) + { + buffers = container._glBuffers[this.renderer.CONTEXT_UID] = this.generateBuffers( container ); + } + + // if the uvs have not updated then no point rendering just yet! + this.renderer.setBlendMode(container.blendMode); + + var gl = this.renderer.gl; + + // var m = container.worldTransform.copy( this.tempMatrix ); +// m.prepend( this.renderer.currentRenderTarget.projectionMatrix ); + this.shader.uniforms.uAlpha = container.worldAlpha; + + + // make sure the texture is bound.. + var baseTexture = children[0]._texture.baseTexture; + + this.renderer.bindTexture(baseTexture); + + // now lets upload and render the buffers.. + for (var i = 0, j = 0; i < totalChildren; i += batchSize, j += 1) + { + var amount = ( totalChildren - i); + if(amount > batchSize) + { + amount = batchSize; + } + + var buffer = buffers[j]; + + // we always upload the dynamic + buffer.uploadDynamic(children, i, amount); + + // we only upload the static content when we have to! + if(container._bufferToUpdate === j) + { + buffer.uploadStatic(children, i, amount); + container._bufferToUpdate = j + 1; + } + + // bind the buffer + buffer.vao.bind( this.shader ) + .draw(gl.TRIANGLES, amount * 6) + .unbind(); + + // now draw those suckas! + // gl.drawElements(gl.TRIANGLES, amount * 6, gl.UNSIGNED_SHORT, 0); + // this.renderer.drawCount++; + } +}; + +/** + * Creates one particle buffer for each child in the container we want to render and updates internal properties + * + * @param container {PIXI.ParticleContainer} The container to render using this ParticleRenderer + */ +ParticleRenderer.prototype.generateBuffers = function (container) +{ + var gl = this.renderer.gl, + buffers = [], + size = container._maxSize, + batchSize = container._batchSize, + dynamicPropertyFlags = container._properties, + i; + + for (i = 0; i < size; i += batchSize) + { + buffers.push(new ParticleBuffer(gl, this.properties, dynamicPropertyFlags, batchSize)); + } + + return buffers; +}; + +/** + * Uploads the verticies. + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their vertices uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadVertices = function (children, startIndex, amount, array, stride, offset) +{ + var sprite, + texture, + trim, + sx, + sy, + w0, w1, h0, h1; + + for (var i = 0; i < amount; i++) { + + sprite = children[startIndex + i]; + texture = sprite._texture; + sx = sprite.scale.x; + sy = sprite.scale.y; + var trim = texture.trim, crop = texture.crop; + + if (trim) + { + // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. + w1 = trim.x - sprite.anchor.x * crop.width; + w0 = w1 + trim.width; + + h1 = trim.y - sprite.anchor.y * crop.height; + h0 = h1 + trim.height; + + } + else + { + w0 = (crop.width ) * (1-sprite.anchor.x); + w1 = (crop.width ) * -sprite.anchor.x; + + h0 = crop.height * (1-sprite.anchor.y); + h1 = crop.height * -sprite.anchor.y; + } + + array[offset] = w1 * sx; + array[offset + 1] = h1 * sy; + + array[offset + stride] = w0 * sx; + array[offset + stride + 1] = h1 * sy; + + array[offset + stride * 2] = w0 * sx; + array[offset + stride * 2 + 1] = h0 * sy; + + array[offset + stride * 3] = w1 * sx; + array[offset + stride * 3 + 1] = h0 * sy; + + offset += stride * 4; + } + +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their positions uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadPosition = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var spritePosition = children[startIndex + i].position; + + array[offset] = spritePosition.x; + array[offset + 1] = spritePosition.y; + + array[offset + stride] = spritePosition.x; + array[offset + stride + 1] = spritePosition.y; + + array[offset + stride * 2] = spritePosition.x; + array[offset + stride * 2 + 1] = spritePosition.y; + + array[offset + stride * 3] = spritePosition.x; + array[offset + stride * 3 + 1] = spritePosition.y; + + offset += stride * 4; + } + +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their rotation uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadRotation = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var spriteRotation = children[startIndex + i].rotation; + + + array[offset] = spriteRotation; + array[offset + stride] = spriteRotation; + array[offset + stride * 2] = spriteRotation; + array[offset + stride * 3] = spriteRotation; + + offset += stride * 4; + } +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their Uvs uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadUvs = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var textureUvs = children[startIndex + i]._texture._uvs; + + if (textureUvs) + { + array[offset] = textureUvs.x0; + array[offset + 1] = textureUvs.y0; + + array[offset + stride] = textureUvs.x1; + array[offset + stride + 1] = textureUvs.y1; + + array[offset + stride * 2] = textureUvs.x2; + array[offset + stride * 2 + 1] = textureUvs.y2; + + array[offset + stride * 3] = textureUvs.x3; + array[offset + stride * 3 + 1] = textureUvs.y3; + + offset += stride * 4; + } + else + { + //TODO you know this can be easier! + array[offset] = 0; + array[offset + 1] = 0; + + array[offset + stride] = 0; + array[offset + stride + 1] = 0; + + array[offset + stride * 2] = 0; + array[offset + stride * 2 + 1] = 0; + + array[offset + stride * 3] = 0; + array[offset + stride * 3 + 1] = 0; + + offset += stride * 4; + } + } +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their alpha uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadAlpha = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var spriteAlpha = children[startIndex + i].alpha; + + array[offset] = spriteAlpha; + array[offset + stride] = spriteAlpha; + array[offset + stride * 2] = spriteAlpha; + array[offset + stride * 3] = spriteAlpha; + + offset += stride * 4; + } +}; + + +/** + * Destroys the ParticleRenderer. + * + */ +ParticleRenderer.prototype.destroy = function () +{ + if (this.renderer.gl) { + this.renderer.gl.deleteBuffer(this.indexBuffer); + } + + ObjectRenderer.prototype.destroy.apply(this, arguments); + + this.shader.destroy(); + + this.indices = null; + this.tempMatrix = null; +}; + +},{"../../core":57,"./ParticleBuffer":142,"./ParticleShader":144}],144:[function(require,module,exports){ +var Shader = require('pixi-gl-core').GLShader; + +/** + * @class + * @extends PIXI.TextureShader + * @memberof PIXI + * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. + */ +function ParticleShader(gl) +{ + Shader.call(this, + gl, + // vertex shader + [ + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + 'attribute float aColor;', + + 'attribute vec2 aPositionCoord;', + 'attribute vec2 aScale;', + 'attribute float aRotation;', + + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + 'varying float vColor;', + + 'void main(void){', + ' vec2 v = aVertexPosition;', + + ' v.x = (aVertexPosition.x) * cos(aRotation) - (aVertexPosition.y) * sin(aRotation);', + ' v.y = (aVertexPosition.x) * sin(aRotation) + (aVertexPosition.y) * cos(aRotation);', + ' v = v + aPositionCoord;', + + ' gl_Position = vec4((projectionMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);', + + ' vTextureCoord = aTextureCoord;', + ' vColor = aColor;', + '}' + ].join('\n'), + // hello + [ + 'precision lowp float;', + + 'varying vec2 vTextureCoord;', + 'varying float vColor;', + + 'uniform sampler2D uSampler;', + 'uniform float uAlpha;', + + 'void main(void){', + ' vec4 color = texture2D(uSampler, vTextureCoord) * vColor * uAlpha;', + ' if (color.a == 0.0) discard;', + ' gl_FragColor = color;', + '}' + ].join('\n') + ); + + // TEMP HACK + +} + +ParticleShader.prototype = Object.create(Shader.prototype); +ParticleShader.prototype.constructor = ParticleShader; + +module.exports = ParticleShader; + +},{"pixi-gl-core":1}],145:[function(require,module,exports){ // References: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign @@ -25722,7 +27779,7 @@ }; } -},{}],136:[function(require,module,exports){ +},{}],146:[function(require,module,exports){ // References: // https://github.com/sindresorhus/object-assign // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign @@ -25732,12 +27789,17 @@ Object.assign = require('object-assign'); } -},{"object-assign":13}],137:[function(require,module,exports){ +},{"object-assign":28}],147:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); -},{"./Math.sign":135,"./Object.assign":136,"./requestAnimationFrame":138}],138:[function(require,module,exports){ +if(!window.ArrayBuffer)window.ArrayBuffer = Array; +if(!window.Float32Array)window.Float32Array = Array; +if(!window.Uint32Array)window.Uint32Array = Array; +if(!window.Uint16Array)window.Uint16Array = Array; + +},{"./Math.sign":145,"./Object.assign":146,"./requestAnimationFrame":148}],148:[function(require,module,exports){ (function (global){ // References: // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ diff --git a/bin/pixi.js b/bin/pixi.js index 85518a9..1d99b5e 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -1,4 +1,1164 @@ (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; +} + +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); +} + +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 + * @param gl {WebGLRenderingContext} + */ + +var Framebuffer = function(gl, width, height) +{ + this.gl = gl; + + this.framebuffer = gl.createFramebuffer(); + + this.stencil = null; + this.texture = null; + + this.width = width || 100; + this.height = height || 100; +} + +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); +} + +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 ); +} + +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); +} + +Framebuffer.prototype.bind = function() +{ + var gl = this.gl; + + if(this.texture) + { + this.texture.unbind(); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); +} + +Framebuffer.prototype.unbind = function() +{ + gl.bindFramebuffer(gl.FRAMEBUFFER, null ); +} + +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); + } +} + +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; +} + +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; +} + +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 + * @param gl {WebGLRenderingContext} + */ +var Shader = function(gl, vertexSrc, fragmentSrc) +{ + this.gl = gl; + + // First compile the program.. + this.program = compileProgram(gl, vertexSrc, fragmentSrc); + + // next extract the attributes + this.attributes = extractAttributes(gl, this.program); + + var uniformData = extractUniforms(gl, this.program); + + this.uniforms = generateUniformAccessObject( gl, uniformData ); +} + +Shader.prototype.bind = function() +{ + this.gl.useProgram(this.program); +} + +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 + * @param gl {WebGLRenderingContext} a 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) +{ + this.gl = gl; + + this.texture = gl.createTexture(); + + // some settings.. + this.mipmap = false; + + this.premultiplyAlpha = false; + + this.width = width || 0; + this.height = height || 0; + + this.format = format || gl.RGBA; + this.type = type || gl.UNSIGNED_BYTE; + + +} + +/** + * @param {PIXI.glCore.Texture} [varname] [description] + */ +Texture.prototype.upload = function(source) +{ + this.bind(); + + var gl = this.gl; + + this.width = source.width; + this.height = 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; + +Texture.prototype.uploadData = function(data, width, height) +{ + this.bind(); + + 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); + +} + +Texture.prototype.bind = function(location) +{ + var gl = this.gl; + + if(location !== undefined) + { + gl.activeTexture(gl.TEXTURE0 + location); + } + + gl.bindTexture(gl.TEXTURE_2D, this.texture); +} + +Texture.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindTexture(gl.TEXTURE_2D, null); +} + +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); + } +} + +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); +} + +Texture.prototype.enableMipmap = function() +{ + this.bind(); + + this.mipmap = true; + gl.generateMipmap(gl.TEXTURE_2D); +} + +Texture.prototype.enableLinearScaling = function() +{ + this.minFilter(true); + this.magFilter(true); +} + +Texture.prototype.enableNearestScaling = function() +{ + this.minFilter(false); + this.magFilter(false); +} + +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); +} + +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); +} + +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); +} + + + +Texture.prototype.destroy = function() +{ + var gl = this.gl; + //TODO + gl.deleteTexture(this.texture); +} + +//Texture. +Texture.fromSource = function(gl, source, premultiplyAlpha) +{ + var texture = new Texture(gl); + texture.premultiplyAlpha = premultiplyAlpha || false; + texture.upload(source); + + return 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){ + +/** + * Generic Mask Stack data structure + * @class + * @memberof PIXI + */ + +// state object// + + +function VertexArrayObject(gl) +{ + + this.nativeVaoExtension = ( + gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object') + ); + +// this.nativeVaoExtension = null; + + if(this.nativeVaoExtension) + { + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + } + + this.gl = gl; + + this.attributes = []; + + this.indexBuffer = null; + + this.dirty = false; + + +} + +VertexArrayObject.prototype.constructor = VertexArrayObject; +module.exports = VertexArrayObject; + +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; +} + +VertexArrayObject.prototype.unbind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + return this; +} + +VertexArrayObject.prototype.activate = function() +{ + var gl = this.gl; + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + attrib.buffer.bind(); + + //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); + + gl.enableVertexAttribArray(attrib.attribute.location); + }; + + this.indexBuffer.bind(); + + return this; +} + +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; +} + + +VertexArrayObject.prototype.addIndex = function(buffer, options) +{ + this.indexBuffer = buffer; + + this.dirty = true; + + return this; +} + +VertexArrayObject.prototype.clear = function() +{ + // 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); + } + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + gl.disableVertexAttribArray(attrib.attribute.location); + }; + + this.attributes.length = 0; + this.indexBuffer = null; + + return this; +} + +VertexArrayObject.prototype.draw = function(type, size, start) +{ + var gl = this.gl; + gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); + + return this; +} + + +},{}],7:[function(require,module,exports){ + +/** + * Helper class to create a webGL Context + * + * @class + * @memberof PIXI + * @param gl {WebGLRenderingContext} + */ + + + +var createContext = function(canvas, options) +{ + 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){ +/** + * Generic Mask Stack data structure + * @class + * @memberof PIXI + */ + +var GL_MAP = {}; + + +var setVertexAttribArrays = function (gl, attribs) +{ + // console.log(gl.id) + var data = GL_MAP[gl.id]; + + if(!data) + { + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + data = GL_MAP[gl.id] = {tempAttribState:new Array(maxAttribs) + ,attribState:new Array(maxAttribs)}; + } + + var i, + tempAttribState = data.tempAttribState, + attribState = data.attribState; + + for (i = 0; i < tempAttribState.length; i++) + { + tempAttribState[i] = false; + } + + // set the new attribs + for (i in attribs) + { + tempAttribState[attribs[i].location] = true; + } + + for (i = 1; i < attribState.length; i++) + { + if (attribState[i] !== tempAttribState[i]) + { + attribState[i] = tempAttribState[i]; + + if (data.attribState[i]) + { + gl.enableVertexAttribArray(i); + } + else + { + gl.disableVertexAttribArray(i); + } + } + } +}; + +module.exports = setVertexAttribArrays; +},{}],9:[function(require,module,exports){ + + + + +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; +} + +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'); + +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:function(type, normalized, stride, start){ + + // console.log(this.location) + gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); + + } + } + }; + + return attributes; +} + +module.exports = extractAttributes; + + +},{"./mapSize":14,"./mapType":15}],12:[function(require,module,exports){ +var mapType = require('./mapType'); +var defaultValue = require('./defaultValue'); + + +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){ + +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); +} + +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); +} + +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 @@ -1267,7 +2427,7 @@ }()); }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"_process":5}],2:[function(require,module,exports){ +},{"_process":20}],17:[function(require,module,exports){ /** * Bit twiddling hacks for JavaScript. * @@ -1473,9 +2633,9 @@ } -},{}],3:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ -},{}],4:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ (function (process){ // Copyright Joyent, Inc. and other Node contributors. // @@ -1703,7 +2863,7 @@ ; }).call(this,require('_process')) -},{"_process":5}],5:[function(require,module,exports){ +},{"_process":20}],20:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -1796,7 +2956,7 @@ }; process.umask = function() { return 0; }; -},{}],6:[function(require,module,exports){ +},{}],21:[function(require,module,exports){ (function (global){ /*! https://mths.be/punycode v1.4.0 by @mathias */ ;(function(root) { @@ -2333,7 +3493,7 @@ }(this)); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],7:[function(require,module,exports){ +},{}],22:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -2419,7 +3579,7 @@ return Object.prototype.toString.call(xs) === '[object Array]'; }; -},{}],8:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -2506,13 +3666,13 @@ return res; }; -},{}],9:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ 'use strict'; exports.decode = exports.parse = require('./decode'); exports.encode = exports.stringify = require('./encode'); -},{"./decode":7,"./encode":8}],10:[function(require,module,exports){ +},{"./decode":22,"./encode":23}],25:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -3221,7 +4381,7 @@ return arg == null; } -},{"punycode":6,"querystring":9}],11:[function(require,module,exports){ +},{"punycode":21,"querystring":24}],26:[function(require,module,exports){ 'use strict'; module.exports = earcut; @@ -3807,7 +4967,7 @@ this.steiner = false; } -},{}],12:[function(require,module,exports){ +},{}],27:[function(require,module,exports){ 'use strict'; // @@ -4071,7 +5231,7 @@ module.exports = EventEmitter; } -},{}],13:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ /* eslint-disable no-unused-vars */ 'use strict'; var hasOwnProperty = Object.prototype.hasOwnProperty; @@ -4112,1155 +5272,6 @@ 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){ - -/** - * Helper class to create a webGL buffer - * - * @class - * @memberof PIXI - * @param gl {WebGLRenderingContext} - */ - -var EMPTY_ARRAY_BUFFER = new ArrayBuffer(0); - -var Buffer = function(gl, type, data, drawType) -{ - this.gl = gl; - - this.buffer = gl.createBuffer(); - this.type = type || gl.ARRAY_BUFFER; - this.drawType = drawType || gl.STATIC_DRAW; - this.data = EMPTY_ARRAY_BUFFER; - - if(data) - { - this.upload(data); - } -} - - -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; -} - -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); -} - -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 - * @param gl {WebGLRenderingContext} - */ - -var Framebuffer = function(gl, width, height) -{ - this.gl = gl; - - this.framebuffer = gl.createFramebuffer(); - - this.stencil = null; - this.texture = null; - - this.width = width || 100; - this.height = height || 100; -} - -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); -} - -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 ); -} - -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); -} - -Framebuffer.prototype.bind = function() -{ - var gl = this.gl; - - if(this.texture) - { - this.texture.unbind(); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); -} - -Framebuffer.prototype.unbind = function() -{ - gl.bindFramebuffer(gl.FRAMEBUFFER, null ); -} - -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); - } -} - -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; -} - -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; -} - -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 - * @param gl {WebGLRenderingContext} - */ -var Shader = function(gl, vertexSrc, fragmentSrc) -{ - this.gl = gl; - - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc); - - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - var uniformData = extractUniforms(gl, this.program); - - this.uniforms = generateUniformAccessObject( gl, uniformData ); -} - -Shader.prototype.bind = function() -{ - this.gl.useProgram(this.program); -} - -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 - * @param gl {WebGLRenderingContext} a 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) -{ - this.gl = gl; - - this.texture = gl.createTexture(); - - // some settings.. - this.mipmap = false; - - this.premultiplyAlpha = false; - - this.width = width || 0; - this.height = height || 0; - - this.format = format || gl.RGBA; - this.type = type || gl.UNSIGNED_BYTE; - - -} - -/** - * @param {PIXI.glCore.Texture} [varname] [description] - */ -Texture.prototype.upload = function(source) -{ - this.bind(); - - var gl = this.gl; - - this.width = source.width; - this.height = 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; - -Texture.prototype.uploadData = function(data, width, height) -{ - this.bind(); - - 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); - -} - -Texture.prototype.bind = function(location) -{ - var gl = this.gl; - - if(location !== undefined) - { - gl.activeTexture(gl.TEXTURE0 + location); - } - - gl.bindTexture(gl.TEXTURE_2D, this.texture); -} - -Texture.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, null); -} - -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); - } -} - -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); -} - -Texture.prototype.enableMipmap = function() -{ - this.bind(); - - this.mipmap = true; - gl.generateMipmap(gl.TEXTURE_2D); -} - -Texture.prototype.enableLinearScaling = function() -{ - this.minFilter(true); - this.magFilter(true); -} - -Texture.prototype.enableNearestScaling = function() -{ - this.minFilter(false); - this.magFilter(false); -} - -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); -} - -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); -} - -Texture.prototype.destroy = function() -{ - var gl = this.gl; - //TODO - gl.deleteTexture(this.texture); -} - -//Texture. -Texture.fromSource = function(gl, source, premultiplyAlpha) -{ - var texture = new Texture(gl); - texture.premultiplyAlpha = premultiplyAlpha || false; - texture.upload(source); - - return 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){ - -/** - * Generic Mask Stack data structure - * @class - * @memberof PIXI - */ - -// state object// - - -function VertexArrayObject(gl) -{ - - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); - -// this.nativeVaoExtension = null; - - if(this.nativeVaoExtension) - { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - } - - this.gl = gl; - - this.attributes = []; - - this.indexBuffer = null; - - this.dirty = false; - - -} - -VertexArrayObject.prototype.constructor = VertexArrayObject; -module.exports = VertexArrayObject; - -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; -} - -VertexArrayObject.prototype.unbind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(null); - } - - return this; -} - -VertexArrayObject.prototype.activate = function() -{ - var gl = this.gl; - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - attrib.buffer.bind(); - - //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); - - gl.enableVertexAttribArray(attrib.attribute.location); - }; - - this.indexBuffer.bind(); - - return this; -} - -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; -} - - -VertexArrayObject.prototype.addIndex = function(buffer, options) -{ - this.indexBuffer = buffer; - - this.dirty = true; - - return this; -} - -VertexArrayObject.prototype.clear = function() -{ - // 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); - } - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - gl.disableVertexAttribArray(attrib.attribute.location); - }; - - this.attributes.length = 0; - this.indexBuffer = null; - - return this; -} - -VertexArrayObject.prototype.draw = function(type, size, start) -{ - var gl = this.gl; - gl.drawElements(type, size, gl.UNSIGNED_SHORT, start); - - return this; -} - - -},{}],20:[function(require,module,exports){ - -/** - * Helper class to create a webGL Context - * - * @class - * @memberof PIXI - * @param gl {WebGLRenderingContext} - */ - - - -var createContext = function(canvas, options) -{ - 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){ -/** - * Generic Mask Stack data structure - * @class - * @memberof PIXI - */ - -var GL_MAP = {}; - - -var setVertexAttribArrays = function (gl, attribs) -{ - // console.log(gl.id) - var data = GL_MAP[gl.id]; - - if(!data) - { - var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - data = GL_MAP[gl.id] = {tempAttribState:new Array(maxAttribs) - ,attribState:new Array(maxAttribs)}; - } - - var i, - tempAttribState = data.tempAttribState, - attribState = data.attribState; - - for (i = 0; i < tempAttribState.length; i++) - { - tempAttribState[i] = false; - } - - // set the new attribs - for (i in attribs) - { - tempAttribState[attribs[i].location] = true; - } - - for (i = 1; i < attribState.length; i++) - { - if (attribState[i] !== tempAttribState[i]) - { - attribState[i] = tempAttribState[i]; - - if (data.attribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } - } - } -}; - -module.exports = setVertexAttribArrays; -},{}],22:[function(require,module,exports){ - - - - -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; -} - -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'); - -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:function(type, normalized, stride, start){ - - // console.log(this.location) - gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); - - } - } - }; - - return attributes; -} - -module.exports = extractAttributes; - - -},{"./mapSize":27,"./mapType":28}],25:[function(require,module,exports){ -var mapType = require('./mapType'); -var defaultValue = require('./defaultValue'); - - -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){ - -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); -} - -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); -} - -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){ /*! @@ -6388,7 +6399,7 @@ }()); }).call(this,require('_process')) -},{"_process":5}],30:[function(require,module,exports){ +},{"_process":20}],30:[function(require,module,exports){ var async = require('async'), urlParser = require('url'), Resource = require('./Resource'), @@ -6846,7 +6857,7 @@ Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; -},{"./Resource":31,"async":29,"eventemitter3":12,"url":10}],31:[function(require,module,exports){ +},{"./Resource":31,"async":29,"eventemitter3":27,"url":25}],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 @@ -7648,7 +7659,7 @@ map[extname] = val; } -},{"eventemitter3":12,"url":10}],32:[function(require,module,exports){ +},{"eventemitter3":27,"url":25}],32:[function(require,module,exports){ module.exports = { // private property @@ -8431,6 +8442,37 @@ }, /** + * The wrap modes that are supported by pixi. + * + * The DEFAULT wrap mode affects the default wraping mode of future operations. + * It can be re-assigned to either CLAMP or REPEAT, depending upon suitability. + * If the texture is non power of two then clamp will be used regardless as webGL can only use REPEAT if the texture is po2 + * This property only affects WebGL + * @static + * @constant + * @property {object} WRAP_MODES + * @property {number} WRAP_MODES.DEFAULT=CLAMP + * @property {number} WRAP_MODES.CLAMP The textures uvs are clamped + * @property {number} WRAP_MODES.REPEAT The texture uvs tile and repeat + * @property {number} WRAP_MODES.MIRRORED_REPEAT The texture uvs tile and repeat with mirroring + */ + WRAP_MODES: { + DEFAULT: 0, + CLAMP: 0, + REPEAT: 1, + MIRRORED_REPEAT:2 + }, + + /** + * If set to true WebGL will attempt make textures mimpaped by default + * Mipmapping will only succeed if the base texture uploaded has power of two dimensions + * @static + * @constant + * @property {bool} MIPMAP_TEXTURES + */ + MIPMAP_TEXTURES:true, + + /** * The prefix that denotes a URL is for a retina asset * * @static @@ -9639,7 +9681,7 @@ this.filterArea = null; }; -},{"../const":40,"../math":61,"../textures/RenderTexture":97,"./Transform":43,"eventemitter3":12}],43:[function(require,module,exports){ +},{"../const":40,"../math":61,"../textures/RenderTexture":97,"./Transform":43,"eventemitter3":27}],43:[function(require,module,exports){ var math = require('../math'); @@ -11544,7 +11586,7 @@ this.glIndices = null; }; -},{"pixi-gl-core":14}],50:[function(require,module,exports){ +},{"pixi-gl-core":1}],50:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -11596,7 +11638,7 @@ module.exports = PrimitiveShader; -},{"pixi-gl-core":14}],51:[function(require,module,exports){ +},{"pixi-gl-core":1}],51:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -12054,7 +12096,7 @@ module.exports = buildPoly; -},{"../../../utils":104,"./buildLine":53,"earcut":11}],55:[function(require,module,exports){ +},{"../../../utils":104,"./buildLine":53,"earcut":26}],55:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -12277,9 +12319,7 @@ // sprites Sprite: require('./sprites/Sprite'), CanvasSpriteRender: require('./sprites/canvas/CanvasSpriteRenderer'), - //ParticleContainer: require('./particles/ParticleContainer'), SpriteRenderer: require('./sprites/webgl/SpriteRenderer'), - //ParticleRenderer: require('./particles/webgl/ParticleRenderer'), // text Text: require('./text/Text'), @@ -12347,7 +12387,7 @@ } }); -},{"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./graphics/Graphics":44,"./graphics/GraphicsData":45,"./graphics/canvas/CanvasGraphicsRenderer":46,"./graphics/webgl/GraphicsRenderer":48,"./math":61,"./renderers/canvas/CanvasRenderer":68,"./renderers/canvas/utils/CanvasRenderTarget":70,"./renderers/webgl/WebGLRenderer":74,"./renderers/webgl/filters/Filter":76,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":79,"./renderers/webgl/managers/WebGLManager":83,"./renderers/webgl/utils/ObjectRenderer":84,"./renderers/webgl/utils/RenderTarget":86,"./sprites/Sprite":89,"./sprites/canvas/CanvasSpriteRenderer":90,"./sprites/webgl/SpriteRenderer":92,"./text/Text":94,"./textures/BaseRenderTexture":95,"./textures/BaseTexture":96,"./textures/RenderTexture":97,"./textures/Texture":98,"./textures/TextureUvs":99,"./textures/VideoBaseTexture":100,"./ticker":102,"./utils":104,"pixi-gl-core":14}],58:[function(require,module,exports){ +},{"./const":40,"./display/Container":41,"./display/DisplayObject":42,"./graphics/Graphics":44,"./graphics/GraphicsData":45,"./graphics/canvas/CanvasGraphicsRenderer":46,"./graphics/webgl/GraphicsRenderer":48,"./math":61,"./renderers/canvas/CanvasRenderer":68,"./renderers/canvas/utils/CanvasRenderTarget":70,"./renderers/webgl/WebGLRenderer":74,"./renderers/webgl/filters/Filter":76,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":79,"./renderers/webgl/managers/WebGLManager":83,"./renderers/webgl/utils/ObjectRenderer":84,"./renderers/webgl/utils/RenderTarget":86,"./sprites/Sprite":89,"./sprites/canvas/CanvasSpriteRenderer":90,"./sprites/webgl/SpriteRenderer":92,"./text/Text":94,"./textures/BaseRenderTexture":95,"./textures/BaseTexture":96,"./textures/RenderTexture":97,"./textures/Texture":98,"./textures/TextureUvs":99,"./textures/VideoBaseTexture":100,"./ticker":102,"./utils":104,"pixi-gl-core":1}],58:[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]; @@ -13846,7 +13886,7 @@ this._lastObjectRendered = null; }; -},{"../const":40,"../display/Container":41,"../math":61,"../textures/RenderTexture":97,"../utils":104,"eventemitter3":12}],68:[function(require,module,exports){ +},{"../const":40,"../display/Container":41,"../math":61,"../textures/RenderTexture":97,"../utils":104,"eventemitter3":27}],68:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), CanvasMaskManager = require('./utils/CanvasMaskManager'), CanvasRenderTarget = require('./utils/CanvasRenderTarget'), @@ -14535,8 +14575,33 @@ this._managedTextures.push(texture); - //TODO check is power of two.. - glTexture.enableWrapClamp(); + + + + if(texture.isPowerOfTwo) + { + if(texture.mipmap) + { + glTexture.enableMipmap(); + } + + if(texture.wrapMode === CONST.WRAP_MODES.CLAMP) + { + glTexture.enableWrapClamp(); + } + else if(texture.wrapMode === CONST.WRAP_MODES.REPEAT) + { + glTexture.enableWrapRepeat(); + } + else + { + glTexture.enableWrapMirrorRepeat(); + } + } + else + { + glTexture.enableWrapClamp(); + } if(texture.scaleMode === CONST.SCALE_MODES.NEAREST) { @@ -14546,6 +14611,8 @@ { glTexture.enableLinearScaling(); } + + } if(isRenderTexture) @@ -14619,7 +14686,7 @@ module.exports = TextureManager; -},{"../../const":40,"../../utils":104,"./utils/RenderTarget":86,"pixi-gl-core":14}],74:[function(require,module,exports){ +},{"../../const":40,"../../utils":104,"./utils/RenderTarget":86,"pixi-gl-core":1}],74:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), @@ -14713,7 +14780,8 @@ * * @member {PIXI.ObjectRenderer} */ - this.currentRenderer = new ObjectRenderer(this); + this.emptyRenderer = new ObjectRenderer(this); + this.currentRenderer = this.emptyRenderer; this.initPlugins(); @@ -14849,6 +14917,16 @@ }; /** + * This shoudl be called if you wish to do some custom rendering + * It will basically render anything that may be batched up such as sprites + * + */ +WebGLRenderer.prototype.flush = function () +{ + this.setObjectRenderer(this.emptyRenderer) +} + +/** * Resizes the webGL view to the specified width and height. * * @param width {number} the new width of the webGL view @@ -15064,7 +15142,7 @@ // this = null; }; -},{"../../const":40,"../../utils":104,"../SystemRenderer":67,"./TextureManager":73,"./WebGLState":75,"./managers/FilterManager":80,"./managers/MaskManager":81,"./managers/StencilManager":82,"./utils/ObjectRenderer":84,"./utils/RenderTarget":86,"./utils/mapWebGLDrawModesToPixi":88,"pixi-gl-core":14}],75:[function(require,module,exports){ +},{"../../const":40,"../../utils":104,"../SystemRenderer":67,"./TextureManager":73,"./WebGLState":75,"./managers/FilterManager":80,"./managers/MaskManager":81,"./managers/StencilManager":82,"./utils/ObjectRenderer":84,"./utils/RenderTarget":86,"./utils/mapWebGLDrawModesToPixi":88,"pixi-gl-core":1}],75:[function(require,module,exports){ var mapWebGLBlendModesToPixi = require('./utils/mapWebGLBlendModesToPixi'); @@ -15388,7 +15466,7 @@ '}' ].join('\n'); -},{"../../../math":61,"./extractUniformsFromSrc":77,"pixi-gl-core":14}],77:[function(require,module,exports){ +},{"../../../math":61,"./extractUniformsFromSrc":77,"pixi-gl-core":1}],77:[function(require,module,exports){ var defaultValue = require('pixi-gl-core/lib/shader/defaultValue'); var mapSize = require('pixi-gl-core/lib/shader/mapSize'); @@ -15450,7 +15528,7 @@ } module.exports = extractUniformsFromSrc; -},{"pixi-gl-core/lib/shader/defaultValue":23,"pixi-gl-core/lib/shader/mapSize":27}],78:[function(require,module,exports){ +},{"pixi-gl-core/lib/shader/defaultValue":10,"pixi-gl-core/lib/shader/mapSize":14}],78:[function(require,module,exports){ var math = require('../../../math'); /* @@ -15612,7 +15690,7 @@ }; }).call(this,"/src/core/renderers/webgl/filters/spriteMask") -},{"../../../../math":61,"../Filter":76,"fs":3}],80:[function(require,module,exports){ +},{"../../../../math":61,"../Filter":76,"fs":18}],80:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), RenderTarget = require('../utils/RenderTarget'), @@ -15963,7 +16041,7 @@ FilterManager.pool = {} -},{"../../../const":40,"../../../math":61,"../../../utils":104,"../filters/filterTransforms":78,"../utils/Quad":85,"../utils/RenderTarget":86,"./WebGLManager":83,"bit-twiddle":2,"pixi-gl-core":14}],81:[function(require,module,exports){ +},{"../../../const":40,"../../../math":61,"../../../utils":104,"../filters/filterTransforms":78,"../utils/Quad":85,"../utils/RenderTarget":86,"./WebGLManager":83,"bit-twiddle":17,"pixi-gl-core":1}],81:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), AlphaMaskFilter = require('../filters/spriteMask/SpriteMaskFilter'); @@ -16521,7 +16599,7 @@ -},{"../../../utils/createIndicesForQuads":103,"pixi-gl-core":14}],86:[function(require,module,exports){ +},{"../../../utils/createIndicesForQuads":103,"pixi-gl-core":1}],86:[function(require,module,exports){ var math = require('../../../math'), utils = require('../../../utils'), CONST = require('../../../const'), @@ -16842,7 +16920,7 @@ this.texture = null; }; -},{"../../../const":40,"../../../math":61,"../../../utils":104,"pixi-gl-core":14}],87:[function(require,module,exports){ +},{"../../../const":40,"../../../math":61,"../../../utils":104,"pixi-gl-core":1}],87:[function(require,module,exports){ CONST = require('../../../const'); /** @@ -18167,13 +18245,13 @@ this.colors = null; } -},{"../../const":40,"../../renderers/webgl/WebGLRenderer":74,"../../renderers/webgl/utils/ObjectRenderer":84,"../../utils/createIndicesForQuads":103,"./generateMultiTextureShader":93,"bit-twiddle":2,"pixi-gl-core":14}],93:[function(require,module,exports){ +},{"../../const":40,"../../renderers/webgl/WebGLRenderer":74,"../../renderers/webgl/utils/ObjectRenderer":84,"../../utils/createIndicesForQuads":103,"./generateMultiTextureShader":93,"bit-twiddle":17,"pixi-gl-core":1}],93:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; function generateMultiTextureShader(gl, maxTextures) { - var vertexSrc = "precision lowp float;\n#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vTextureId = aTextureId;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}"; + var vertexSrc = "#define GLSLIFY 1\nprecision lowp float;\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vTextureId = aTextureId;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}"; var fragmentSrc = fragTemplate fragmentSrc = fragmentSrc.replace(/\%count\%/gi, maxTextures); @@ -18232,7 +18310,7 @@ module.exports = generateMultiTextureShader; -},{"pixi-gl-core":14}],94:[function(require,module,exports){ +},{"pixi-gl-core":1}],94:[function(require,module,exports){ var Sprite = require('../sprites/Sprite'), Texture = require('../textures/Texture'), math = require('../math'), @@ -19144,7 +19222,8 @@ },{"../const":40,"../math":61,"../renderers/webgl/managers/FilterManager":80,"../renderers/webgl/utils/RenderTarget":86,"./BaseTexture":96,"./Texture":98}],96:[function(require,module,exports){ var utils = require('../utils'), CONST = require('../const'), - EventEmitter = require('eventemitter3'); + EventEmitter = require('eventemitter3'), + bitTwiddle = require('bit-twiddle'); /** * A texture stores the information that represents an image. All textures have a base texture. @@ -19272,7 +19351,17 @@ * * @member {boolean} */ - this.mipmap = false; + this.mipmap = CONST.MIPMAP_TEXTURES; + + + /** + * + * Set this to true if a mipmap of this texture needs to be generated. This value needs to be set before the texture is used + * Also the texture must be a power of two size to work + * + * @member {boolean} + */ + this.wrap = CONST.MIPMAP_TEXTURES; /** * A map of renderer IDs to webgl textures @@ -19324,7 +19413,7 @@ this.width = this.realWidth / this.resolution; this.height = this.realHeight / this.resolution; - this.isPowerOfTwo = utils.isPowerOfTwo(this.realWidth, this.realHeight); + this.isPowerOfTwo = bitTwiddle.isPow2(this.realWidth) && bitTwiddle.isPow2(this.realHeight); this.emit('update', this); }; @@ -19579,7 +19668,7 @@ return baseTexture; }; -},{"../const":40,"../utils":104,"eventemitter3":12}],97:[function(require,module,exports){ +},{"../const":40,"../utils":104,"bit-twiddle":17,"eventemitter3":27}],97:[function(require,module,exports){ var BaseRenderTexture = require('./BaseRenderTexture'), Texture = require('./Texture'), math = require('../math'), @@ -20130,7 +20219,7 @@ */ Texture.EMPTY = new Texture(new BaseTexture()); -},{"../math":61,"../utils":104,"./BaseTexture":96,"./TextureUvs":99,"./VideoBaseTexture":100,"eventemitter3":12}],99:[function(require,module,exports){ +},{"../math":61,"../utils":104,"./BaseTexture":96,"./TextureUvs":99,"./VideoBaseTexture":100,"eventemitter3":27}],99:[function(require,module,exports){ /** * A standard object to store the Uvs of a texture @@ -20815,7 +20904,7 @@ module.exports = Ticker; -},{"../const":40,"eventemitter3":12}],102:[function(require,module,exports){ +},{"../const":40,"eventemitter3":27}],102:[function(require,module,exports){ var Ticker = require('./Ticker'); /** @@ -20971,46 +21060,6 @@ return ((rgb[0]*255 << 16) + (rgb[1]*255 << 8) + rgb[2]*255); }, - - - /** - * Given a number, this function returns the closest number that is a power of two - * this function is taken from Starling Framework as its pretty neat ;) - * - * @param number {number} - * @return {number} the closest number that is a power of two - */ - getNextPowerOfTwo: function (number) - { - // see: http://en.wikipedia.org/wiki/Power_of_two#Fast_algorithm_to_check_if_a_positive_number_is_a_power_of_two - if (number > 0 && (number & (number - 1)) === 0) - { - return number; - } - else - { - var result = 1; - - while (result < number) - { - result <<= 1; - } - - return result; - } - }, - - /** - * checks if the given width and height make a power of two rectangle - * - * @param width {number} - * @param height {number} - * @return {boolean} - */ - isPowerOfTwo: function (width, height) - { - return (width > 0 && (width & (width - 1)) === 0 && height > 0 && (height & (height - 1)) === 0); - }, /** * get the resolution of an asset by looking for the prefix @@ -21148,7 +21197,7 @@ BaseTextureCache: {} }; -},{"../const":40,"./pluginTarget":105,"async":1,"eventemitter3":12}],105:[function(require,module,exports){ +},{"../const":40,"./pluginTarget":105,"async":16,"eventemitter3":27}],105:[function(require,module,exports){ /** * Mixins functionality to make an object have "plugins". * @@ -23576,9 +23625,9 @@ { core.Filter.call(this, // vertex shader - "precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", + "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform float m[20];\n\nvoid main(void)\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n gl_FragColor.r += (m[1] * c.g);\n gl_FragColor.r += (m[2] * c.b);\n gl_FragColor.r += (m[3] * c.a);\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n gl_FragColor.g += (m[6] * c.g);\n gl_FragColor.g += (m[7] * c.b);\n gl_FragColor.g += (m[8] * c.a);\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n gl_FragColor.b += (m[11] * c.g);\n gl_FragColor.b += (m[12] * c.b);\n gl_FragColor.b += (m[13] * c.a);\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n gl_FragColor.a += (m[16] * c.g);\n gl_FragColor.a += (m[17] * c.b);\n gl_FragColor.a += (m[18] * c.a);\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform float m[20];\n\nvoid main(void)\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n gl_FragColor.r += (m[1] * c.g);\n gl_FragColor.r += (m[2] * c.b);\n gl_FragColor.r += (m[3] * c.a);\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n gl_FragColor.g += (m[6] * c.g);\n gl_FragColor.g += (m[7] * c.b);\n gl_FragColor.g += (m[8] * c.a);\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n gl_FragColor.b += (m[11] * c.g);\n gl_FragColor.b += (m[12] * c.b);\n gl_FragColor.b += (m[13] * c.a);\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n gl_FragColor.a += (m[16] * c.g);\n gl_FragColor.a += (m[17] * c.b);\n gl_FragColor.a += (m[18] * c.a);\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\n}\n" ); this.uniforms.m = [ @@ -24109,7 +24158,7 @@ // vertex shader "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMapCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n}\n" ); @@ -24181,9 +24230,9 @@ { core.Filter.call(this, // vertex shader - "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", + "#define GLSLIFY 1\nprecision lowp float;\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float gray;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float gray;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n}\n" ); this.uniforms.gray = 1; @@ -24272,7 +24321,7 @@ "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}\n\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n{\n coord *= filterArea.xy;\n coord += filterArea.zw;\n\n return coord;\n}\n\nvec2 unmapCoord( vec2 coord )\n{\n coord -= filterArea.zw;\n coord /= filterArea.xy;\n\n return coord;\n}\n\nvec2 twist(vec2 coord)\n{\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratioDist = (radius - dist) / radius;\n float angleMod = ratioDist * ratioDist * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n coord += offset;\n\n return coord;\n}\n\nvoid main(void)\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n" + "#define GLSLIFY 1\nprecision mediump float;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n{\n coord *= filterArea.xy;\n coord += filterArea.zw;\n\n return coord;\n}\n\nvec2 unmapCoord( vec2 coord )\n{\n coord -= filterArea.zw;\n coord /= filterArea.xy;\n\n return coord;\n}\n\nvec2 twist(vec2 coord)\n{\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratioDist = (radius - dist) / radius;\n float angleMod = ratioDist * ratioDist * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n coord += offset;\n\n return coord;\n}\n\nvoid main(void)\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n" ); this.uniforms.radius = 400; @@ -24367,7 +24416,8 @@ core.filters = require('./filters'); core.interaction = require('./interaction'); core.loaders = require('./loaders'); -//core.mesh = require('./mesh'); +core.mesh = require('./mesh'); +core.particles = require('./particles'); core.accessibility = require('./accessibility'); // export a premade loader instance @@ -24387,7 +24437,7 @@ global.PIXI = core; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./accessibility":38,"./core":57,"./deprecation":106,"./extras":113,"./filters":123,"./interaction":128,"./loaders":131,"./polyfill":137}],126:[function(require,module,exports){ +},{"./accessibility":38,"./core":57,"./deprecation":106,"./extras":113,"./filters":123,"./interaction":128,"./loaders":131,"./mesh":138,"./particles":141,"./polyfill":147}],126:[function(require,module,exports){ var core = require('../core'); /** @@ -25529,7 +25579,7 @@ }; }; -},{"../core":57,"../extras":113,"path":4,"resource-loader":33}],131:[function(require,module,exports){ +},{"../core":57,"../extras":113,"path":19,"resource-loader":33}],131:[function(require,module,exports){ /** * @file Main export of the PIXI loaders library * @author Mat Groves @@ -25684,7 +25734,7 @@ }; }; -},{"../core":57,"path":4,"resource-loader":33}],134:[function(require,module,exports){ +},{"../core":57,"path":19,"resource-loader":33}],134:[function(require,module,exports){ var core = require('../core'); module.exports = function () @@ -25707,6 +25757,2013 @@ }; },{"../core":57}],135:[function(require,module,exports){ +var core = require('../core'), + glCore = require('pixi-gl-core'), + Shader = require('./webgl/MeshShader'), + tempPoint = new core.Point(), + tempPolygon = new core.Polygon(); + +/** + * Base mesh class + * @class + * @extends PIXI.Container + * @memberof PIXI.mesh + * @param texture {PIXI.Texture} The texture to use + * @param [vertices] {Float32Array} if you want to specify the vertices + * @param [uvs] {Float32Array} if you want to specify the uvs + * @param [indices] {Uint16Array} if you want to specify the indices + * @param [drawMode] {number} the drawMode, can be any of the Mesh.DRAW_MODES consts + */ +function Mesh(texture, vertices, uvs, indices, drawMode) +{ + core.Container.call(this); + + /** + * The texture of the Mesh + * + * @member {PIXI.Texture} + * @private + */ + this._texture = null; + + /** + * The Uvs of the Mesh + * + * @member {Float32Array} + */ + this.uvs = uvs || new Float32Array([0, 0, + 1, 0, + 1, 1, + 0, 1]); + + /** + * An array of vertices + * + * @member {Float32Array} + */ + this.vertices = vertices || new Float32Array([0, 0, + 100, 0, + 100, 100, + 0, 100]); + + /* + * @member {Uint16Array} An array containing the indices of the vertices + */ + // TODO auto generate this based on draw mode! + this.indices = indices || new Uint16Array([0, 1, 3, 2]); + + /** + * Whether the Mesh is dirty or not + * + * @member {boolean} + */ + this.dirty = true; + + /** + * The blend mode to be applied to the sprite. Set to `PIXI.BLEND_MODES.NORMAL` to remove any blend mode. + * + * @member {number} + * @default PIXI.BLEND_MODES.NORMAL + * @see PIXI.BLEND_MODES + */ + this.blendMode = core.BLEND_MODES.NORMAL; + + /** + * Triangles in canvas mode are automatically antialiased, use this value to force triangles to overlap a bit with each other. + * + * @member {number} + */ + this.canvasPadding = 0; + + /** + * The way the Mesh should be drawn, can be any of the {@link PIXI.mesh.Mesh.DRAW_MODES} consts + * + * @member {number} + * @see PIXI.mesh.Mesh.DRAW_MODES + */ + this.drawMode = drawMode || Mesh.DRAW_MODES.TRIANGLE_MESH; + + // run texture setter; + this.texture = texture; + + /** + * The default shader that is used if a mesh doesn't have a more specific one. + * + * @member {PIXI.Shader} + */ + this.shader = null; + + this._glDatas = []; +} + +// constructor +Mesh.prototype = Object.create(core.Container.prototype); +Mesh.prototype.constructor = Mesh; +module.exports = Mesh; + +Object.defineProperties(Mesh.prototype, { + /** + * The texture that the sprite is using + * + * @member {PIXI.Texture} + * @memberof PIXI.mesh.Mesh# + */ + texture: { + get: function () + { + return this._texture; + }, + set: function (value) + { + if (this._texture === value) + { + return; + } + + this._texture = value; + + if (value) + { + // wait for the texture to load + if (value.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + value.once('update', this._onTextureUpdate, this); + } + } + } + } +}); + +/** + * Renders the object using the WebGL renderer + * + * @param renderer {PIXI.WebGLRenderer} a reference to the WebGL renderer + * @private + */ +Mesh.prototype._renderWebGL = function (renderer) +{ + // get rid of any thing that may be batching. + renderer.flush(); + + // renderer.plugins.mesh.render(this); + var gl = renderer.gl; + var glData = this._glDatas[renderer.CONTEXT_UID]; + + if(!glData) + { + glData = { + shader:new Shader(gl), + vertexBuffer:glCore.GLBuffer.createVertexBuffer(gl, this.vertices, gl.STREAM_DRAW), + uvBuffer:glCore.GLBuffer.createVertexBuffer(gl, this.uvs, gl.STREAM_DRAW), + indexBuffer:glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW), + // build the vao object that will render.. + vao:new glCore.VertexArrayObject(gl) + } + + // build the vao object that will render.. + glData.vao = new glCore.VertexArrayObject(gl) + .addIndex(glData.indexBuffer) + .addAttribute(glData.vertexBuffer, glData.shader.attributes.aVertexPosition, gl.FLOAT, false, 2 * 4, 0) + .addAttribute(glData.uvBuffer, glData.shader.attributes.aTextureCoord, gl.FLOAT, false, 2 * 4, 0) + + this._glDatas[renderer.CONTEXT_UID] = glData; + } + + if(this.dirty) + { + this.dirty = false; + glData.uvBuffer.upload(); + } + + glData.vertexBuffer.upload(); + + renderer.bindShader(glData.shader); + renderer.bindTexture(this._texture, 0); + + glData.shader.uniforms.translationMatrix = this.worldTransform.toArray(true); + glData.shader.uniforms.alpha = this.worldAlpha; + + var drawMode = this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH ? gl.TRIANGLE_STRIP : gl.TRIANGLES; + + + glData.vao.bind() + .draw(drawMode, this.indices.length) + .unbind(); +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {PIXI.CanvasRenderer} + * @private + */ +Mesh.prototype._renderCanvas = function (renderer) +{ + var context = renderer.context; + + var transform = this.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx | 0, transform.ty | 0); + } + else + { + context.setTransform(transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty); + } + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLE_MESH) + { + this._renderCanvasTriangleMesh(context); + } + else + { + this._renderCanvasTriangles(context); + } +}; + +/** + * Draws the object in Triangle Mesh mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangleMesh = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + + var length = vertices.length / 2; + // this.count++; + + for (var i = 0; i < length - 2; i++) + { + // draw some triangles! + var index = i * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index, (index + 2), (index + 4)); + } +}; + +/** + * Draws the object in triangle mode using canvas + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @private + */ +Mesh.prototype._renderCanvasTriangles = function (context) +{ + // draw triangles!! + var vertices = this.vertices; + var uvs = this.uvs; + var indices = this.indices; + + var length = indices.length; + // this.count++; + + for (var i = 0; i < length; i += 3) + { + // draw some triangles! + var index0 = indices[i] * 2, index1 = indices[i + 1] * 2, index2 = indices[i + 2] * 2; + this._renderCanvasDrawTriangle(context, vertices, uvs, index0, index1, index2); + } +}; + +/** + * Draws one of the triangles that form this Mesh + * + * @param context {CanvasRenderingContext2D} the current drawing context + * @param vertices {Float32Array} a reference to the vertices of the Mesh + * @param uvs {Float32Array} a reference to the uvs of the Mesh + * @param index0 {number} the index of the first vertex + * @param index1 {number} the index of the second vertex + * @param index2 {number} the index of the third vertex + * @private + */ +Mesh.prototype._renderCanvasDrawTriangle = function (context, vertices, uvs, index0, index1, index2) +{ + var textureSource = this._texture.baseTexture.source; + var textureWidth = this._texture.baseTexture.width; + var textureHeight = this._texture.baseTexture.height; + + var x0 = vertices[index0], x1 = vertices[index1], x2 = vertices[index2]; + var y0 = vertices[index0 + 1], y1 = vertices[index1 + 1], y2 = vertices[index2 + 1]; + + var u0 = uvs[index0] * textureWidth, u1 = uvs[index1] * textureWidth, u2 = uvs[index2] * textureWidth; + var v0 = uvs[index0 + 1] * textureHeight, v1 = uvs[index1 + 1] * textureHeight, v2 = uvs[index2 + 1] * textureHeight; + + if (this.canvasPadding > 0) + { + var paddingX = this.canvasPadding / this.worldTransform.a; + var paddingY = this.canvasPadding / this.worldTransform.d; + var centerX = (x0 + x1 + x2) / 3; + var centerY = (y0 + y1 + y2) / 3; + + var normX = x0 - centerX; + var normY = y0 - centerY; + + var dist = Math.sqrt(normX * normX + normY * normY); + x0 = centerX + (normX / dist) * (dist + paddingX); + y0 = centerY + (normY / dist) * (dist + paddingY); + + // + + normX = x1 - centerX; + normY = y1 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x1 = centerX + (normX / dist) * (dist + paddingX); + y1 = centerY + (normY / dist) * (dist + paddingY); + + normX = x2 - centerX; + normY = y2 - centerY; + + dist = Math.sqrt(normX * normX + normY * normY); + x2 = centerX + (normX / dist) * (dist + paddingX); + y2 = centerY + (normY / dist) * (dist + paddingY); + } + + context.save(); + context.beginPath(); + + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + + context.closePath(); + + context.clip(); + + // Compute matrix transform + var delta = (u0 * v1) + (v0 * u2) + (u1 * v2) - (v1 * u2) - (v0 * u1) - (u0 * v2); + var deltaA = (x0 * v1) + (v0 * x2) + (x1 * v2) - (v1 * x2) - (v0 * x1) - (x0 * v2); + var deltaB = (u0 * x1) + (x0 * u2) + (u1 * x2) - (x1 * u2) - (x0 * u1) - (u0 * x2); + var deltaC = (u0 * v1 * x2) + (v0 * x1 * u2) + (x0 * u1 * v2) - (x0 * v1 * u2) - (v0 * u1 * x2) - (u0 * x1 * v2); + var deltaD = (y0 * v1) + (v0 * y2) + (y1 * v2) - (v1 * y2) - (v0 * y1) - (y0 * v2); + var deltaE = (u0 * y1) + (y0 * u2) + (u1 * y2) - (y1 * u2) - (y0 * u1) - (u0 * y2); + var deltaF = (u0 * v1 * y2) + (v0 * y1 * u2) + (y0 * u1 * v2) - (y0 * v1 * u2) - (v0 * u1 * y2) - (u0 * y1 * v2); + + context.transform(deltaA / delta, deltaD / delta, + deltaB / delta, deltaE / delta, + deltaC / delta, deltaF / delta); + + context.drawImage(textureSource, 0, 0); + context.restore(); +}; + + + +/** + * Renders a flat Mesh + * + * @param Mesh {PIXI.mesh.Mesh} The Mesh to render + * @private + */ +Mesh.prototype.renderMeshFlat = function (Mesh) +{ + var context = this.context; + var vertices = Mesh.vertices; + + var length = vertices.length/2; + // this.count++; + + context.beginPath(); + for (var i=1; i < length-2; i++) + { + // draw some triangles! + var index = i*2; + + var x0 = vertices[index], x1 = vertices[index+2], x2 = vertices[index+4]; + var y0 = vertices[index+1], y1 = vertices[index+3], y2 = vertices[index+5]; + + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + } + + context.fillStyle = '#FF0000'; + context.fill(); + context.closePath(); +}; + +/** + * When the texture is updated, this event will fire to update the scale and frame + * + * @param event + * @private + */ +Mesh.prototype._onTextureUpdate = function () +{ + this.updateFrame = true; +}; + +/** + * Returns the bounds of the mesh as a rectangle. The bounds calculation takes the worldTransform into account. + * + * @param matrix {PIXI.Matrix} the transformation matrix of the sprite + * @return {PIXI.Rectangle} the framing rectangle + */ +Mesh.prototype.getBounds = function (matrix) +{ + if (!this._currentBounds) { + var worldTransform = matrix || this.worldTransform; + + var a = worldTransform.a; + var b = worldTransform.b; + var c = worldTransform.c; + var d = worldTransform.d; + var tx = worldTransform.tx; + var ty = worldTransform.ty; + + var maxX = -Infinity; + var maxY = -Infinity; + + var minX = Infinity; + var minY = Infinity; + + var vertices = this.vertices; + for (var i = 0, n = vertices.length; i < n; i += 2) { + var rawX = vertices[i], rawY = vertices[i + 1]; + var x = (a * rawX) + (c * rawY) + tx; + var y = (d * rawY) + (b * rawX) + ty; + + minX = x < minX ? x : minX; + minY = y < minY ? y : minY; + + maxX = x > maxX ? x : maxX; + maxY = y > maxY ? y : maxY; + } + + if (minX === -Infinity || maxY === Infinity) { + return core.Rectangle.EMPTY; + } + + var bounds = this._bounds; + + bounds.x = minX; + bounds.width = maxX - minX; + + bounds.y = minY; + bounds.height = maxY - minY; + + // store a reference so that if this function gets called again in the render cycle we do not have to recalculate + this._currentBounds = bounds; + } + + return this._currentBounds; +}; + +/** + * Tests if a point is inside this mesh. Works only for TRIANGLE_MESH + * + * @param point {PIXI.Point} the point to test + * @return {boolean} the result of the test + */ +Mesh.prototype.containsPoint = function( point ) { + if (!this.getBounds().contains(point.x, point.y)) { + return false; + } + this.worldTransform.applyInverse(point, tempPoint); + + var vertices = this.vertices; + var points = tempPolygon.points; + var i, len; + + if (this.drawMode === Mesh.DRAW_MODES.TRIANGLES) { + var indices = this.indices; + len = this.indices.length; + //TODO: inline this. + for (i=0;i 1) + { + ratio = 1; + } + + perpLength = Math.sqrt(perpX * perpX + perpY * perpY); + num = this._texture.height / 2; //(20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + perpX /= perpLength; + perpY /= perpLength; + + perpX *= num; + perpY *= num; + + vertices[index] = point.x + perpX; + vertices[index+1] = point.y + perpY; + vertices[index+2] = point.x - perpX; + vertices[index+3] = point.y - perpY; + + lastPoint = point; + } + + this.containerUpdateTransform(); +}; + +},{"../core":57,"./Mesh":135}],138:[function(require,module,exports){ +/** + * @file Main export of the PIXI extras library + * @author Mat Groves + * @copyright 2013-2015 GoodBoyDigital + * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License} + */ + +/** + * @namespace PIXI.mesh + */ +module.exports = { + Mesh: require('./Mesh'), + Plane: require('./Plane'), + Rope: require('./Rope'), + MeshShader: require('./webgl/MeshShader') +}; + +},{"./Mesh":135,"./Plane":136,"./Rope":137,"./webgl/MeshShader":139}],139:[function(require,module,exports){ +var Shader = require('pixi-gl-core').GLShader; + +/** + * @class + * @extends PIXI.Shader + * @memberof PIXI.mesh + * @param shaderManager {PIXI.ShaderManager} The WebGL shader manager this shader works for. + */ +function MeshShader(gl) +{ + Shader.call(this, + gl, + // vertex shader + [ + 'precision lowp float;', + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + + 'uniform mat3 translationMatrix;', + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + + 'void main(void){', + ' gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);', + ' vTextureCoord = aTextureCoord;', + '}' + ].join('\n'), + [ + 'precision lowp float;', + + 'varying vec2 vTextureCoord;', + 'uniform float alpha;', + + 'uniform sampler2D uSampler;', + + 'void main(void){', + ' gl_FragColor = texture2D(uSampler, vTextureCoord) * alpha ;', + // ' gl_FragColor = vec4(1.0);', + '}' + ].join('\n') + ); +} + +MeshShader.prototype = Object.create(Shader.prototype); +MeshShader.prototype.constructor = MeshShader; +module.exports = MeshShader; + + +},{"pixi-gl-core":1}],140:[function(require,module,exports){ +var core = require('../core'); + +/** + * The ParticleContainer class is a really fast version of the Container built solely for speed, + * so use when you need a lot of sprites or particles. The tradeoff of the ParticleContainer is that advanced + * functionality will not work. ParticleContainer implements only the basic object transform (position, scale, rotation). + * Any other functionality like tinting, masking, etc will not work on sprites in this batch. + * + * It's extremely easy to use : + * + * ```js + * var container = new ParticleContainer(); + * + * for (var i = 0; i < 100; ++i) + * { + * var sprite = new PIXI.Sprite.fromImage("myImage.png"); + * container.addChild(sprite); + * } + * ``` + * + * And here you have a hundred sprites that will be renderer at the speed of light. + * + * @class + * @extends PIXI.Container + * @memberof PIXI + * @param [maxSize=15000] {number} The maximum number of particles that can be renderer by the container. + * @param [properties] {object} The properties of children that should be uploaded to the gpu and applied. + * @param [properties.scale=false] {boolean} When true, scale be uploaded and applied. + * @param [properties.position=true] {boolean} When true, position be uploaded and applied. + * @param [properties.rotation=false] {boolean} When true, rotation be uploaded and applied. + * @param [properties.uvs=false] {boolean} When true, uvs be uploaded and applied. + * @param [properties.alpha=false] {boolean} When true, alpha be uploaded and applied. + * @param [batchSize=15000] {number} Number of particles per batch. + */ +function ParticleContainer(maxSize, properties, batchSize) +{ + core.Container.call(this); + + batchSize = batchSize || 15000; //CONST.SPRITE_BATCH_SIZE; // 2000 is a nice balance between mobile / desktop + maxSize = maxSize || 15000; + + // Making sure the batch size is valid + // 65535 is max vertex index in the index buffer (see ParticleRenderer) + // so max number of particles is 65536 / 4 = 16384 + var maxBatchSize = 16384; + if (batchSize > maxBatchSize) { + batchSize = maxBatchSize; + } + + if (batchSize > maxSize) { + batchSize = maxSize; + } + + /** + * Set properties to be dynamic (true) / static (false) + * + * @member {boolean[]} + * @private + */ + this._properties = [false, true, false, false, false]; + + /** + * @member {number} + * @private + */ + this._maxSize = maxSize; + + /** + * @member {number} + * @private + */ + this._batchSize = batchSize; + + /** + * @member {WebGLBuffer} + * @private + */ + this._glBuffers = []; + + /** + * @member {number} + * @private + */ + this._bufferToUpdate = 0; + + /** + * @member {boolean} + * + */ + this.interactiveChildren = false; + + /** + * The blend mode to be applied to the sprite. Apply a value of `PIXI.BLEND_MODES.NORMAL` to reset the blend mode. + * + * @member {number} + * @default PIXI.BLEND_MODES.NORMAL + * @see PIXI.BLEND_MODES + */ + this.blendMode = core.BLEND_MODES.NORMAL; + + /** + * Used for canvas renderering. If true then the elements will be positioned at the nearest pixel. This provides a nice speed boost. + * + * @member {boolean} + * @default true; + */ + this.roundPixels = true; + + this.baseTexture = null; + + this.setProperties(properties); +} + +ParticleContainer.prototype = Object.create(core.Container.prototype); +ParticleContainer.prototype.constructor = ParticleContainer; +module.exports = ParticleContainer; + +/** + * Sets the private properties array to dynamic / static based on the passed properties object + * + * @param properties {object} The properties to be uploaded + */ +ParticleContainer.prototype.setProperties = function(properties) +{ + if ( properties ) { + this._properties[0] = 'scale' in properties ? !!properties.scale : this._properties[0]; + this._properties[1] = 'position' in properties ? !!properties.position : this._properties[1]; + this._properties[2] = 'rotation' in properties ? !!properties.rotation : this._properties[2]; + this._properties[3] = 'uvs' in properties ? !!properties.uvs : this._properties[3]; + this._properties[4] = 'alpha' in properties ? !!properties.alpha : this._properties[4]; + } +}; + +/** + * Updates the object transform for rendering + * + * @private + */ +ParticleContainer.prototype.updateTransform = function () +{ + + // TODO don't need to! + this.displayObjectUpdateTransform(); + // PIXI.Container.prototype.updateTransform.call( this ); +}; + +/** + * Renders the container using the WebGL renderer + * + * @param renderer {PIXI.WebGLRenderer} The webgl renderer + * @private + */ +ParticleContainer.prototype.renderWebGL = function (renderer) +{ + if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable) + { + return; + } + + + if(!this.baseTexture) + { + this.baseTexture = this.children[0]._texture.baseTexture; + if(!this.baseTexture.hasLoaded) + { + this.baseTexture.once('update', function(){ + this.onChildrenChange(0); + }, this) + } + } + + + renderer.setObjectRenderer( renderer.plugins.particle ); + renderer.plugins.particle.render( this ); +}; + +/** + * Set the flag that static data should be updated to true + * + * @private + */ +ParticleContainer.prototype.onChildrenChange = function (smallestChildIndex) +{ + var bufferIndex = Math.floor(smallestChildIndex / this._batchSize); + if (bufferIndex < this._bufferToUpdate) { + this._bufferToUpdate = bufferIndex; + } +}; + +/** + * Renders the object using the Canvas renderer + * + * @param renderer {PIXI.CanvasRenderer} The canvas renderer + * @private + */ +ParticleContainer.prototype.renderCanvas = function (renderer) +{ + if (!this.visible || this.worldAlpha <= 0 || !this.children.length || !this.renderable) + { + return; + } + + var context = renderer.context; + var transform = this.worldTransform; + var isRotated = true; + + var positionX = 0; + var positionY = 0; + + var finalWidth = 0; + var finalHeight = 0; + + var compositeOperation = renderer.blendModes[this.blendMode]; + if (compositeOperation !== context.globalCompositeOperation) + { + context.globalCompositeOperation = compositeOperation; + } + + context.globalAlpha = this.worldAlpha; + + this.displayObjectUpdateTransform(); + + for (var i = 0; i < this.children.length; ++i) + { + var child = this.children[i]; + + if (!child.visible) + { + continue; + } + + var frame = child.texture.frame; + + context.globalAlpha = this.worldAlpha * child.alpha; + + if (child.rotation % (Math.PI * 2) === 0) + { + // this is the fastest way to optimise! - if rotation is 0 then we can avoid any kind of setTransform call + if (isRotated) + { + context.setTransform( + transform.a, + transform.b, + transform.c, + transform.d, + transform.tx, + transform.ty + ); + + isRotated = false; + } + + positionX = ((child.anchor.x) * (-frame.width * child.scale.x) + child.position.x + 0.5); + positionY = ((child.anchor.y) * (-frame.height * child.scale.y) + child.position.y + 0.5); + + finalWidth = frame.width * child.scale.x; + finalHeight = frame.height * child.scale.y; + + } + else + { + if (!isRotated) + { + isRotated = true; + } + + child.displayObjectUpdateTransform(); + + var childTransform = child.worldTransform; + + if (renderer.roundPixels) + { + context.setTransform( + childTransform.a, + childTransform.b, + childTransform.c, + childTransform.d, + childTransform.tx | 0, + childTransform.ty | 0 + ); + } + else + { + context.setTransform( + childTransform.a, + childTransform.b, + childTransform.c, + childTransform.d, + childTransform.tx, + childTransform.ty + ); + } + + positionX = ((child.anchor.x) * (-frame.width) + 0.5); + positionY = ((child.anchor.y) * (-frame.height) + 0.5); + + finalWidth = frame.width; + finalHeight = frame.height; + } + + context.drawImage( + child.texture.baseTexture.source, + frame.x, + frame.y, + frame.width, + frame.height, + positionX, + positionY, + finalWidth, + finalHeight + ); + } +}; + +/** + * Destroys the container + * + * @param [destroyChildren=false] {boolean} if set to true, all the children will have their destroy method called as well + */ +ParticleContainer.prototype.destroy = function () { + Container.prototype.destroy.apply(this, arguments); + + if (this._buffers) { + for (var i = 0; i < this._buffers.length; ++i) { + this._buffers[i].destroy(); + } + } + + this._properties = null; + this._buffers = null; +}; + +},{"../core":57}],141:[function(require,module,exports){ +/** + * @file Main export of the PIXI extras library + * @author Mat Groves + * @copyright 2013-2015 GoodBoyDigital + * @license {@link https://github.com/pixijs/pixi.js/blob/master/LICENSE|MIT License} + */ + +/** + * @namespace PIXI.mesh + */ +module.exports = { + ParticleContainer: require('./ParticleContainer'), + ParticleRenderer: require('./webgl/ParticleRenderer') +}; + +},{"./ParticleContainer":140,"./webgl/ParticleRenderer":143}],142:[function(require,module,exports){ +var glCore = require('pixi-gl-core'), + createIndicesForQuads = require('../../core/utils/createIndicesForQuads'); + +/** + * @author Mat Groves + * + * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ + * for creating the original pixi version! + * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer + * + * Heavily inspired by LibGDX's ParticleBuffer: + * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleBuffer.java + */ + +/** + * The particle buffer manages the static and dynamic buffers for a particle container. + * + * @class + * @private + * @memberof PIXI + */ +function ParticleBuffer(gl, properties, dynamicPropertyFlags, size) +{ + /** + * The current WebGL drawing context. + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * Size of a single vertex. + * + * @member {number} + */ + this.vertSize = 2; + + /** + * Size of a single vertex in bytes. + * + * @member {number} + */ + this.vertByteSize = this.vertSize * 4; + + /** + * The number of particles the buffer can hold + * + * @member {number} + */ + this.size = size; + + /** + * A list of the properties that are dynamic. + * + * @member {object[]} + */ + this.dynamicProperties = []; + + /** + * A list of the properties that are static. + * + * @member {object[]} + */ + this.staticProperties = []; + + for (var i = 0; i < properties.length; i++) + { + var property = properties[i]; + + if(dynamicPropertyFlags[i]) + { + this.dynamicProperties.push(property); + } + else + { + this.staticProperties.push(property); + } + } + + this.staticStride = 0; + this.staticBuffer = null; + this.staticData = null; + + this.dynamicStride = 0; + this.dynamicBuffer = null; + this.dynamicData = null; + + this.initBuffers(); + +} + +ParticleBuffer.prototype.constructor = ParticleBuffer; +module.exports = ParticleBuffer; + +/** + * Sets up the renderer context and necessary buffers. + * + * @private + */ +ParticleBuffer.prototype.initBuffers = function () +{ + var gl = this.gl; + var i; + var property; + + var dynamicOffset = 0; + + + /** + * Holds the indices of the geometry (quads) to draw + * + * @member {Uint16Array} + */ + this.indices = createIndicesForQuads(this.size) + this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); + + + this.dynamicStride = 0; + + for (i = 0; i < this.dynamicProperties.length; i++) + { + property = this.dynamicProperties[i]; + + property.offset = dynamicOffset; + dynamicOffset += property.size; + this.dynamicStride += property.size; + } + + this.dynamicData = new Float32Array( this.size * this.dynamicStride * 4); + this.dynamicBuffer = glCore.GLBuffer.createVertexBuffer(gl, this.dynamicData, gl.STREAM_DRAW); + + // static // + var staticOffset = 0; + this.staticStride = 0; + + for (i = 0; i < this.staticProperties.length; i++) + { + property = this.staticProperties[i]; + + property.offset = staticOffset; + staticOffset += property.size; + this.staticStride += property.size; + + + } + + this.staticData = new Float32Array( this.size * this.staticStride * 4); + this.staticBuffer = glCore.GLBuffer.createVertexBuffer(gl, this.staticData, gl.STATIC_DRAW); + + + this.vao = new glCore.VertexArrayObject(gl) + .addIndex(this.indexBuffer); + + for (i = 0; i < this.dynamicProperties.length; i++) + { + property = this.dynamicProperties[i]; + this.vao.addAttribute(this.dynamicBuffer, property.attribute, gl.FLOAT, false, this.dynamicStride * 4, property.offset * 4); + } + + for (i = 0; i < this.staticProperties.length; i++) + { + property = this.staticProperties[i]; + this.vao.addAttribute(this.staticBuffer, property.attribute, gl.FLOAT, false, this.staticStride * 4, property.offset * 4); + } +}; + +/** + * Uploads the dynamic properties. + * + */ +ParticleBuffer.prototype.uploadDynamic = function(children, startIndex, amount) +{ + var gl = this.gl; + + for (var i = 0; i < this.dynamicProperties.length; i++) + { + var property = this.dynamicProperties[i]; + property.uploadFunction(children, startIndex, amount, this.dynamicData, this.dynamicStride, property.offset); + } + + this.dynamicBuffer.upload(); +}; + +/** + * Uploads the static properties. + * + */ +ParticleBuffer.prototype.uploadStatic = function(children, startIndex, amount) +{ + var gl = this.gl; + + for (var i = 0; i < this.staticProperties.length; i++) + { + var property = this.staticProperties[i]; + property.uploadFunction(children, startIndex, amount, this.staticData, this.staticStride, property.offset); + } + + this.staticBuffer.upload(); +}; + +/** + * Binds the buffers to the GPU + * + */ +ParticleBuffer.prototype.bind = function () +{ + var gl = this.gl; + var i, property; + + this.vao.bind(); +}; + +/** + * Destroys the ParticleBuffer. + * + */ +ParticleBuffer.prototype.destroy = function () +{ + this.dynamicProperties = null; + this.dynamicData = null; + this.dynamicBuffer.destroy(); + + this.staticProperties = null; + this.staticData = null; + this.staticBuffer.destroy(); +}; + +},{"../../core/utils/createIndicesForQuads":103,"pixi-gl-core":1}],143:[function(require,module,exports){ +var core = require('../../core'), + ParticleShader = require('./ParticleShader'), + ParticleBuffer = require('./ParticleBuffer'); + +/** + * @author Mat Groves + * + * Big thanks to the very clever Matt DesLauriers https://github.com/mattdesl/ + * for creating the original pixi version! + * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now share 4 bytes on the vertex buffer + * + * Heavily inspired by LibGDX's ParticleRenderer: + * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/ParticleRenderer.java + */ + +/** + * + * @class + * @private + * @memberof PIXI + * @param renderer {PIXI.WebGLRenderer} The renderer this sprite batch works for. + */ +function ParticleRenderer(renderer) +{ + core.ObjectRenderer.call(this, renderer); + + // 65535 is max vertex index in the index buffer (see ParticleRenderer) + // so max number of particles is 65536 / 4 = 16384 + // and max number of element in the index buffer is 16384 * 6 = 98304 + // Creating a full index buffer, overhead is 98304 * 2 = 196Ko + var numIndices = 98304; + + /** + * The default shader that is used if a sprite doesn't have a more specific one. + * + * @member {PIXI.Shader} + */ + this.shader = null; + + this.indexBuffer = null; + + this.properties = null; + + this.tempMatrix = new core.math.Matrix(); + + this.CONTEXT_UID = 0; +} + +ParticleRenderer.prototype = Object.create(core.ObjectRenderer.prototype); +ParticleRenderer.prototype.constructor = ParticleRenderer; +module.exports = ParticleRenderer; + +core.WebGLRenderer.registerPlugin('particle', ParticleRenderer); + +/** + * When there is a WebGL context change + * + * @private + */ +ParticleRenderer.prototype.onContextChange = function () +{ + var gl = this.renderer.gl; + + this.CONTEXT_UID = this.renderer.CONTEXT_UID; + + // setup default shader + this.shader = new ParticleShader(gl); + + this.properties = [ + // verticesData + { + attribute:this.shader.attributes.aVertexPosition, + size:2, + uploadFunction:this.uploadVertices, + offset:0 + }, + // positionData + { + attribute:this.shader.attributes.aPositionCoord, + size:2, + uploadFunction:this.uploadPosition, + offset:0 + }, + // rotationData + { + attribute:this.shader.attributes.aRotation, + size:1, + uploadFunction:this.uploadRotation, + offset:0 + }, + // uvsData + { + attribute:this.shader.attributes.aTextureCoord, + size:2, + uploadFunction:this.uploadUvs, + offset:0 + }, + // alphaData + { + attribute:this.shader.attributes.aColor, + size:1, + uploadFunction:this.uploadAlpha, + offset:0 + } + ]; + +}; + +/** + * Starts a new particle batch. + * + */ +ParticleRenderer.prototype.start = function () +{ + this.renderer.bindShader(this.shader); +}; + + +/** + * Renders the particle container object. + * + * @param container {PIXI.ParticleContainer} The container to render using this ParticleRenderer + */ +ParticleRenderer.prototype.render = function (container) +{ + var children = container.children, + totalChildren = children.length, + maxSize = container._maxSize, + batchSize = container._batchSize; + + if(totalChildren === 0) + { + return; + } + else if(totalChildren > maxSize) + { + totalChildren = maxSize; + } + + var buffers = container._glBuffers[this.renderer.CONTEXT_UID]; + + if(!buffers) + { + buffers = container._glBuffers[this.renderer.CONTEXT_UID] = this.generateBuffers( container ); + } + + // if the uvs have not updated then no point rendering just yet! + this.renderer.setBlendMode(container.blendMode); + + var gl = this.renderer.gl; + + // var m = container.worldTransform.copy( this.tempMatrix ); +// m.prepend( this.renderer.currentRenderTarget.projectionMatrix ); + this.shader.uniforms.uAlpha = container.worldAlpha; + + + // make sure the texture is bound.. + var baseTexture = children[0]._texture.baseTexture; + + this.renderer.bindTexture(baseTexture); + + // now lets upload and render the buffers.. + for (var i = 0, j = 0; i < totalChildren; i += batchSize, j += 1) + { + var amount = ( totalChildren - i); + if(amount > batchSize) + { + amount = batchSize; + } + + var buffer = buffers[j]; + + // we always upload the dynamic + buffer.uploadDynamic(children, i, amount); + + // we only upload the static content when we have to! + if(container._bufferToUpdate === j) + { + buffer.uploadStatic(children, i, amount); + container._bufferToUpdate = j + 1; + } + + // bind the buffer + buffer.vao.bind( this.shader ) + .draw(gl.TRIANGLES, amount * 6) + .unbind(); + + // now draw those suckas! + // gl.drawElements(gl.TRIANGLES, amount * 6, gl.UNSIGNED_SHORT, 0); + // this.renderer.drawCount++; + } +}; + +/** + * Creates one particle buffer for each child in the container we want to render and updates internal properties + * + * @param container {PIXI.ParticleContainer} The container to render using this ParticleRenderer + */ +ParticleRenderer.prototype.generateBuffers = function (container) +{ + var gl = this.renderer.gl, + buffers = [], + size = container._maxSize, + batchSize = container._batchSize, + dynamicPropertyFlags = container._properties, + i; + + for (i = 0; i < size; i += batchSize) + { + buffers.push(new ParticleBuffer(gl, this.properties, dynamicPropertyFlags, batchSize)); + } + + return buffers; +}; + +/** + * Uploads the verticies. + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their vertices uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadVertices = function (children, startIndex, amount, array, stride, offset) +{ + var sprite, + texture, + trim, + sx, + sy, + w0, w1, h0, h1; + + for (var i = 0; i < amount; i++) { + + sprite = children[startIndex + i]; + texture = sprite._texture; + sx = sprite.scale.x; + sy = sprite.scale.y; + var trim = texture.trim, crop = texture.crop; + + if (trim) + { + // if the sprite is trimmed and is not a tilingsprite then we need to add the extra space before transforming the sprite coords.. + w1 = trim.x - sprite.anchor.x * crop.width; + w0 = w1 + trim.width; + + h1 = trim.y - sprite.anchor.y * crop.height; + h0 = h1 + trim.height; + + } + else + { + w0 = (crop.width ) * (1-sprite.anchor.x); + w1 = (crop.width ) * -sprite.anchor.x; + + h0 = crop.height * (1-sprite.anchor.y); + h1 = crop.height * -sprite.anchor.y; + } + + array[offset] = w1 * sx; + array[offset + 1] = h1 * sy; + + array[offset + stride] = w0 * sx; + array[offset + stride + 1] = h1 * sy; + + array[offset + stride * 2] = w0 * sx; + array[offset + stride * 2 + 1] = h0 * sy; + + array[offset + stride * 3] = w1 * sx; + array[offset + stride * 3 + 1] = h0 * sy; + + offset += stride * 4; + } + +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their positions uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadPosition = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var spritePosition = children[startIndex + i].position; + + array[offset] = spritePosition.x; + array[offset + 1] = spritePosition.y; + + array[offset + stride] = spritePosition.x; + array[offset + stride + 1] = spritePosition.y; + + array[offset + stride * 2] = spritePosition.x; + array[offset + stride * 2 + 1] = spritePosition.y; + + array[offset + stride * 3] = spritePosition.x; + array[offset + stride * 3 + 1] = spritePosition.y; + + offset += stride * 4; + } + +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their rotation uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadRotation = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var spriteRotation = children[startIndex + i].rotation; + + + array[offset] = spriteRotation; + array[offset + stride] = spriteRotation; + array[offset + stride * 2] = spriteRotation; + array[offset + stride * 3] = spriteRotation; + + offset += stride * 4; + } +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their Uvs uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadUvs = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var textureUvs = children[startIndex + i]._texture._uvs; + + if (textureUvs) + { + array[offset] = textureUvs.x0; + array[offset + 1] = textureUvs.y0; + + array[offset + stride] = textureUvs.x1; + array[offset + stride + 1] = textureUvs.y1; + + array[offset + stride * 2] = textureUvs.x2; + array[offset + stride * 2 + 1] = textureUvs.y2; + + array[offset + stride * 3] = textureUvs.x3; + array[offset + stride * 3 + 1] = textureUvs.y3; + + offset += stride * 4; + } + else + { + //TODO you know this can be easier! + array[offset] = 0; + array[offset + 1] = 0; + + array[offset + stride] = 0; + array[offset + stride + 1] = 0; + + array[offset + stride * 2] = 0; + array[offset + stride * 2 + 1] = 0; + + array[offset + stride * 3] = 0; + array[offset + stride * 3 + 1] = 0; + + offset += stride * 4; + } + } +}; + +/** + * + * @param children {PIXI.DisplayObject[]} the array of display objects to render + * @param startIndex {number} the index to start from in the children array + * @param amount {number} the amount of children that will have their alpha uploaded + * @param array {number[]} + * @param stride {number} + * @param offset {number} + */ +ParticleRenderer.prototype.uploadAlpha = function (children,startIndex, amount, array, stride, offset) +{ + for (var i = 0; i < amount; i++) + { + var spriteAlpha = children[startIndex + i].alpha; + + array[offset] = spriteAlpha; + array[offset + stride] = spriteAlpha; + array[offset + stride * 2] = spriteAlpha; + array[offset + stride * 3] = spriteAlpha; + + offset += stride * 4; + } +}; + + +/** + * Destroys the ParticleRenderer. + * + */ +ParticleRenderer.prototype.destroy = function () +{ + if (this.renderer.gl) { + this.renderer.gl.deleteBuffer(this.indexBuffer); + } + + ObjectRenderer.prototype.destroy.apply(this, arguments); + + this.shader.destroy(); + + this.indices = null; + this.tempMatrix = null; +}; + +},{"../../core":57,"./ParticleBuffer":142,"./ParticleShader":144}],144:[function(require,module,exports){ +var Shader = require('pixi-gl-core').GLShader; + +/** + * @class + * @extends PIXI.TextureShader + * @memberof PIXI + * @param shaderManager {ShaderManager} The webgl shader manager this shader works for. + */ +function ParticleShader(gl) +{ + Shader.call(this, + gl, + // vertex shader + [ + 'attribute vec2 aVertexPosition;', + 'attribute vec2 aTextureCoord;', + 'attribute float aColor;', + + 'attribute vec2 aPositionCoord;', + 'attribute vec2 aScale;', + 'attribute float aRotation;', + + 'uniform mat3 projectionMatrix;', + + 'varying vec2 vTextureCoord;', + 'varying float vColor;', + + 'void main(void){', + ' vec2 v = aVertexPosition;', + + ' v.x = (aVertexPosition.x) * cos(aRotation) - (aVertexPosition.y) * sin(aRotation);', + ' v.y = (aVertexPosition.x) * sin(aRotation) + (aVertexPosition.y) * cos(aRotation);', + ' v = v + aPositionCoord;', + + ' gl_Position = vec4((projectionMatrix * vec3(v, 1.0)).xy, 0.0, 1.0);', + + ' vTextureCoord = aTextureCoord;', + ' vColor = aColor;', + '}' + ].join('\n'), + // hello + [ + 'precision lowp float;', + + 'varying vec2 vTextureCoord;', + 'varying float vColor;', + + 'uniform sampler2D uSampler;', + 'uniform float uAlpha;', + + 'void main(void){', + ' vec4 color = texture2D(uSampler, vTextureCoord) * vColor * uAlpha;', + ' if (color.a == 0.0) discard;', + ' gl_FragColor = color;', + '}' + ].join('\n') + ); + + // TEMP HACK + +} + +ParticleShader.prototype = Object.create(Shader.prototype); +ParticleShader.prototype.constructor = ParticleShader; + +module.exports = ParticleShader; + +},{"pixi-gl-core":1}],145:[function(require,module,exports){ // References: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign @@ -25722,7 +27779,7 @@ }; } -},{}],136:[function(require,module,exports){ +},{}],146:[function(require,module,exports){ // References: // https://github.com/sindresorhus/object-assign // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign @@ -25732,12 +27789,17 @@ Object.assign = require('object-assign'); } -},{"object-assign":13}],137:[function(require,module,exports){ +},{"object-assign":28}],147:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); -},{"./Math.sign":135,"./Object.assign":136,"./requestAnimationFrame":138}],138:[function(require,module,exports){ +if(!window.ArrayBuffer)window.ArrayBuffer = Array; +if(!window.Float32Array)window.Float32Array = Array; +if(!window.Uint32Array)window.Uint32Array = Array; +if(!window.Uint16Array)window.Uint16Array = Array; + +},{"./Math.sign":145,"./Object.assign":146,"./requestAnimationFrame":148}],148:[function(require,module,exports){ (function (global){ // References: // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ diff --git a/bin/pixi.js.map b/bin/pixi.js.map index 17b354c..5c02287 100644 --- a/bin/pixi.js.map +++ b/bin/pixi.js.map @@ -1 +1 @@ -{"version":3,"names":[],"mappings":"","sources":["pixi.js"],"sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.PIXI = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= 0 &&\n arr.length % 1 === 0\n );\n }\n\n function _arrayEach(arr, iterator) {\n var index = -1,\n length = arr.length;\n\n while (++index < length) {\n iterator(arr[index], index, arr);\n }\n }\n\n function _map(arr, iterator) {\n var index = -1,\n length = arr.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iterator(arr[index], index, arr);\n }\n return result;\n }\n\n function _range(count) {\n return _map(Array(count), function (v, i) { return i; });\n }\n\n function _reduce(arr, iterator, memo) {\n _arrayEach(arr, function (x, i, a) {\n memo = iterator(memo, x, i, a);\n });\n return memo;\n }\n\n function _forEachOf(object, iterator) {\n _arrayEach(_keys(object), function (key) {\n iterator(object[key], key);\n });\n }\n\n function _indexOf(arr, item) {\n for (var i = 0; i < arr.length; i++) {\n if (arr[i] === item) return i;\n }\n return -1;\n }\n\n var _keys = Object.keys || function (obj) {\n var keys = [];\n for (var k in obj) {\n if (obj.hasOwnProperty(k)) {\n keys.push(k);\n }\n }\n return keys;\n };\n\n function _keyIterator(coll) {\n var i = -1;\n var len;\n var keys;\n if (_isArrayLike(coll)) {\n len = coll.length;\n return function next() {\n i++;\n return i < len ? i : null;\n };\n } else {\n keys = _keys(coll);\n len = keys.length;\n return function next() {\n i++;\n return i < len ? keys[i] : null;\n };\n }\n }\n\n // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)\n // This accumulates the arguments passed into an array, after a given index.\n // From underscore.js (https://github.com/jashkenas/underscore/pull/2140).\n function _restParam(func, startIndex) {\n startIndex = startIndex == null ? func.length - 1 : +startIndex;\n return function() {\n var length = Math.max(arguments.length - startIndex, 0);\n var rest = Array(length);\n for (var index = 0; index < length; index++) {\n rest[index] = arguments[index + startIndex];\n }\n switch (startIndex) {\n case 0: return func.call(this, rest);\n case 1: return func.call(this, arguments[0], rest);\n }\n // Currently unused but handle cases outside of the switch statement:\n // var args = Array(startIndex + 1);\n // for (index = 0; index < startIndex; index++) {\n // args[index] = arguments[index];\n // }\n // args[startIndex] = rest;\n // return func.apply(this, args);\n };\n }\n\n function _withoutIndex(iterator) {\n return function (value, index, callback) {\n return iterator(value, callback);\n };\n }\n\n //// exported async module functions ////\n\n //// nextTick implementation with browser-compatible fallback ////\n\n // capture the global reference to guard against fakeTimer mocks\n var _setImmediate = typeof setImmediate === 'function' && setImmediate;\n\n var _delay = _setImmediate ? function(fn) {\n // not a direct alias for IE10 compatibility\n _setImmediate(fn);\n } : function(fn) {\n setTimeout(fn, 0);\n };\n\n if (typeof process === 'object' && typeof process.nextTick === 'function') {\n async.nextTick = process.nextTick;\n } else {\n async.nextTick = _delay;\n }\n async.setImmediate = _setImmediate ? _delay : async.nextTick;\n\n\n async.forEach =\n async.each = function (arr, iterator, callback) {\n return async.eachOf(arr, _withoutIndex(iterator), callback);\n };\n\n async.forEachSeries =\n async.eachSeries = function (arr, iterator, callback) {\n return async.eachOfSeries(arr, _withoutIndex(iterator), callback);\n };\n\n\n async.forEachLimit =\n async.eachLimit = function (arr, limit, iterator, callback) {\n return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);\n };\n\n async.forEachOf =\n async.eachOf = function (object, iterator, callback) {\n callback = _once(callback || noop);\n object = object || [];\n\n var iter = _keyIterator(object);\n var key, completed = 0;\n\n while ((key = iter()) != null) {\n completed += 1;\n iterator(object[key], key, only_once(done));\n }\n\n if (completed === 0) callback(null);\n\n function done(err) {\n completed--;\n if (err) {\n callback(err);\n }\n // Check key is null in case iterator isn't exhausted\n // and done resolved synchronously.\n else if (key === null && completed <= 0) {\n callback(null);\n }\n }\n };\n\n async.forEachOfSeries =\n async.eachOfSeries = function (obj, iterator, callback) {\n callback = _once(callback || noop);\n obj = obj || [];\n var nextKey = _keyIterator(obj);\n var key = nextKey();\n function iterate() {\n var sync = true;\n if (key === null) {\n return callback(null);\n }\n iterator(obj[key], key, only_once(function (err) {\n if (err) {\n callback(err);\n }\n else {\n key = nextKey();\n if (key === null) {\n return callback(null);\n } else {\n if (sync) {\n async.setImmediate(iterate);\n } else {\n iterate();\n }\n }\n }\n }));\n sync = false;\n }\n iterate();\n };\n\n\n\n async.forEachOfLimit =\n async.eachOfLimit = function (obj, limit, iterator, callback) {\n _eachOfLimit(limit)(obj, iterator, callback);\n };\n\n function _eachOfLimit(limit) {\n\n return function (obj, iterator, callback) {\n callback = _once(callback || noop);\n obj = obj || [];\n var nextKey = _keyIterator(obj);\n if (limit <= 0) {\n return callback(null);\n }\n var done = false;\n var running = 0;\n var errored = false;\n\n (function replenish () {\n if (done && running <= 0) {\n return callback(null);\n }\n\n while (running < limit && !errored) {\n var key = nextKey();\n if (key === null) {\n done = true;\n if (running <= 0) {\n callback(null);\n }\n return;\n }\n running += 1;\n iterator(obj[key], key, only_once(function (err) {\n running -= 1;\n if (err) {\n callback(err);\n errored = true;\n }\n else {\n replenish();\n }\n }));\n }\n })();\n };\n }\n\n\n function doParallel(fn) {\n return function (obj, iterator, callback) {\n return fn(async.eachOf, obj, iterator, callback);\n };\n }\n function doParallelLimit(fn) {\n return function (obj, limit, iterator, callback) {\n return fn(_eachOfLimit(limit), obj, iterator, callback);\n };\n }\n function doSeries(fn) {\n return function (obj, iterator, callback) {\n return fn(async.eachOfSeries, obj, iterator, callback);\n };\n }\n\n function _asyncMap(eachfn, arr, iterator, callback) {\n callback = _once(callback || noop);\n arr = arr || [];\n var results = _isArrayLike(arr) ? [] : {};\n eachfn(arr, function (value, index, callback) {\n iterator(value, function (err, v) {\n results[index] = v;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n\n async.map = doParallel(_asyncMap);\n async.mapSeries = doSeries(_asyncMap);\n async.mapLimit = doParallelLimit(_asyncMap);\n\n // reduce only has a series version, as doing reduce in parallel won't\n // work in many situations.\n async.inject =\n async.foldl =\n async.reduce = function (arr, memo, iterator, callback) {\n async.eachOfSeries(arr, function (x, i, callback) {\n iterator(memo, x, function (err, v) {\n memo = v;\n callback(err);\n });\n }, function (err) {\n callback(err, memo);\n });\n };\n\n async.foldr =\n async.reduceRight = function (arr, memo, iterator, callback) {\n var reversed = _map(arr, identity).reverse();\n async.reduce(reversed, memo, iterator, callback);\n };\n\n async.transform = function (arr, memo, iterator, callback) {\n if (arguments.length === 3) {\n callback = iterator;\n iterator = memo;\n memo = _isArray(arr) ? [] : {};\n }\n\n async.eachOf(arr, function(v, k, cb) {\n iterator(memo, v, k, cb);\n }, function(err) {\n callback(err, memo);\n });\n };\n\n function _filter(eachfn, arr, iterator, callback) {\n var results = [];\n eachfn(arr, function (x, index, callback) {\n iterator(x, function (v) {\n if (v) {\n results.push({index: index, value: x});\n }\n callback();\n });\n }, function () {\n callback(_map(results.sort(function (a, b) {\n return a.index - b.index;\n }), function (x) {\n return x.value;\n }));\n });\n }\n\n async.select =\n async.filter = doParallel(_filter);\n\n async.selectLimit =\n async.filterLimit = doParallelLimit(_filter);\n\n async.selectSeries =\n async.filterSeries = doSeries(_filter);\n\n function _reject(eachfn, arr, iterator, callback) {\n _filter(eachfn, arr, function(value, cb) {\n iterator(value, function(v) {\n cb(!v);\n });\n }, callback);\n }\n async.reject = doParallel(_reject);\n async.rejectLimit = doParallelLimit(_reject);\n async.rejectSeries = doSeries(_reject);\n\n function _createTester(eachfn, check, getResult) {\n return function(arr, limit, iterator, cb) {\n function done() {\n if (cb) cb(getResult(false, void 0));\n }\n function iteratee(x, _, callback) {\n if (!cb) return callback();\n iterator(x, function (v) {\n if (cb && check(v)) {\n cb(getResult(true, x));\n cb = iterator = false;\n }\n callback();\n });\n }\n if (arguments.length > 3) {\n eachfn(arr, limit, iteratee, done);\n } else {\n cb = iterator;\n iterator = limit;\n eachfn(arr, iteratee, done);\n }\n };\n }\n\n async.any =\n async.some = _createTester(async.eachOf, toBool, identity);\n\n async.someLimit = _createTester(async.eachOfLimit, toBool, identity);\n\n async.all =\n async.every = _createTester(async.eachOf, notId, notId);\n\n async.everyLimit = _createTester(async.eachOfLimit, notId, notId);\n\n function _findGetResult(v, x) {\n return x;\n }\n async.detect = _createTester(async.eachOf, identity, _findGetResult);\n async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);\n async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);\n\n async.sortBy = function (arr, iterator, callback) {\n async.map(arr, function (x, callback) {\n iterator(x, function (err, criteria) {\n if (err) {\n callback(err);\n }\n else {\n callback(null, {value: x, criteria: criteria});\n }\n });\n }, function (err, results) {\n if (err) {\n return callback(err);\n }\n else {\n callback(null, _map(results.sort(comparator), function (x) {\n return x.value;\n }));\n }\n\n });\n\n function comparator(left, right) {\n var a = left.criteria, b = right.criteria;\n return a < b ? -1 : a > b ? 1 : 0;\n }\n };\n\n async.auto = function (tasks, concurrency, callback) {\n if (typeof arguments[1] === 'function') {\n // concurrency is optional, shift the args.\n callback = concurrency;\n concurrency = null;\n }\n callback = _once(callback || noop);\n var keys = _keys(tasks);\n var remainingTasks = keys.length;\n if (!remainingTasks) {\n return callback(null);\n }\n if (!concurrency) {\n concurrency = remainingTasks;\n }\n\n var results = {};\n var runningTasks = 0;\n\n var hasError = false;\n\n var listeners = [];\n function addListener(fn) {\n listeners.unshift(fn);\n }\n function removeListener(fn) {\n var idx = _indexOf(listeners, fn);\n if (idx >= 0) listeners.splice(idx, 1);\n }\n function taskComplete() {\n remainingTasks--;\n _arrayEach(listeners.slice(0), function (fn) {\n fn();\n });\n }\n\n addListener(function () {\n if (!remainingTasks) {\n callback(null, results);\n }\n });\n\n _arrayEach(keys, function (k) {\n if (hasError) return;\n var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];\n var taskCallback = _restParam(function(err, args) {\n runningTasks--;\n if (args.length <= 1) {\n args = args[0];\n }\n if (err) {\n var safeResults = {};\n _forEachOf(results, function(val, rkey) {\n safeResults[rkey] = val;\n });\n safeResults[k] = args;\n hasError = true;\n\n callback(err, safeResults);\n }\n else {\n results[k] = args;\n async.setImmediate(taskComplete);\n }\n });\n var requires = task.slice(0, task.length - 1);\n // prevent dead-locks\n var len = requires.length;\n var dep;\n while (len--) {\n if (!(dep = tasks[requires[len]])) {\n throw new Error('Has nonexistent dependency in ' + requires.join(', '));\n }\n if (_isArray(dep) && _indexOf(dep, k) >= 0) {\n throw new Error('Has cyclic dependencies');\n }\n }\n function ready() {\n return runningTasks < concurrency && _reduce(requires, function (a, x) {\n return (a && results.hasOwnProperty(x));\n }, true) && !results.hasOwnProperty(k);\n }\n if (ready()) {\n runningTasks++;\n task[task.length - 1](taskCallback, results);\n }\n else {\n addListener(listener);\n }\n function listener() {\n if (ready()) {\n runningTasks++;\n removeListener(listener);\n task[task.length - 1](taskCallback, results);\n }\n }\n });\n };\n\n\n\n async.retry = function(times, task, callback) {\n var DEFAULT_TIMES = 5;\n var DEFAULT_INTERVAL = 0;\n\n var attempts = [];\n\n var opts = {\n times: DEFAULT_TIMES,\n interval: DEFAULT_INTERVAL\n };\n\n function parseTimes(acc, t){\n if(typeof t === 'number'){\n acc.times = parseInt(t, 10) || DEFAULT_TIMES;\n } else if(typeof t === 'object'){\n acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;\n acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;\n } else {\n throw new Error('Unsupported argument type for \\'times\\': ' + typeof t);\n }\n }\n\n var length = arguments.length;\n if (length < 1 || length > 3) {\n throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');\n } else if (length <= 2 && typeof times === 'function') {\n callback = task;\n task = times;\n }\n if (typeof times !== 'function') {\n parseTimes(opts, times);\n }\n opts.callback = callback;\n opts.task = task;\n\n function wrappedTask(wrappedCallback, wrappedResults) {\n function retryAttempt(task, finalAttempt) {\n return function(seriesCallback) {\n task(function(err, result){\n seriesCallback(!err || finalAttempt, {err: err, result: result});\n }, wrappedResults);\n };\n }\n\n function retryInterval(interval){\n return function(seriesCallback){\n setTimeout(function(){\n seriesCallback(null);\n }, interval);\n };\n }\n\n while (opts.times) {\n\n var finalAttempt = !(opts.times-=1);\n attempts.push(retryAttempt(opts.task, finalAttempt));\n if(!finalAttempt && opts.interval > 0){\n attempts.push(retryInterval(opts.interval));\n }\n }\n\n async.series(attempts, function(done, data){\n data = data[data.length - 1];\n (wrappedCallback || opts.callback)(data.err, data.result);\n });\n }\n\n // If a callback is passed, run this as a controll flow\n return opts.callback ? wrappedTask() : wrappedTask;\n };\n\n async.waterfall = function (tasks, callback) {\n callback = _once(callback || noop);\n if (!_isArray(tasks)) {\n var err = new Error('First argument to waterfall must be an array of functions');\n return callback(err);\n }\n if (!tasks.length) {\n return callback();\n }\n function wrapIterator(iterator) {\n return _restParam(function (err, args) {\n if (err) {\n callback.apply(null, [err].concat(args));\n }\n else {\n var next = iterator.next();\n if (next) {\n args.push(wrapIterator(next));\n }\n else {\n args.push(callback);\n }\n ensureAsync(iterator).apply(null, args);\n }\n });\n }\n wrapIterator(async.iterator(tasks))();\n };\n\n function _parallel(eachfn, tasks, callback) {\n callback = callback || noop;\n var results = _isArrayLike(tasks) ? [] : {};\n\n eachfn(tasks, function (task, key, callback) {\n task(_restParam(function (err, args) {\n if (args.length <= 1) {\n args = args[0];\n }\n results[key] = args;\n callback(err);\n }));\n }, function (err) {\n callback(err, results);\n });\n }\n\n async.parallel = function (tasks, callback) {\n _parallel(async.eachOf, tasks, callback);\n };\n\n async.parallelLimit = function(tasks, limit, callback) {\n _parallel(_eachOfLimit(limit), tasks, callback);\n };\n\n async.series = function(tasks, callback) {\n _parallel(async.eachOfSeries, tasks, callback);\n };\n\n async.iterator = function (tasks) {\n function makeCallback(index) {\n function fn() {\n if (tasks.length) {\n tasks[index].apply(null, arguments);\n }\n return fn.next();\n }\n fn.next = function () {\n return (index < tasks.length - 1) ? makeCallback(index + 1): null;\n };\n return fn;\n }\n return makeCallback(0);\n };\n\n async.apply = _restParam(function (fn, args) {\n return _restParam(function (callArgs) {\n return fn.apply(\n null, args.concat(callArgs)\n );\n });\n });\n\n function _concat(eachfn, arr, fn, callback) {\n var result = [];\n eachfn(arr, function (x, index, cb) {\n fn(x, function (err, y) {\n result = result.concat(y || []);\n cb(err);\n });\n }, function (err) {\n callback(err, result);\n });\n }\n async.concat = doParallel(_concat);\n async.concatSeries = doSeries(_concat);\n\n async.whilst = function (test, iterator, callback) {\n callback = callback || noop;\n if (test()) {\n var next = _restParam(function(err, args) {\n if (err) {\n callback(err);\n } else if (test.apply(this, args)) {\n iterator(next);\n } else {\n callback.apply(null, [null].concat(args));\n }\n });\n iterator(next);\n } else {\n callback(null);\n }\n };\n\n async.doWhilst = function (iterator, test, callback) {\n var calls = 0;\n return async.whilst(function() {\n return ++calls <= 1 || test.apply(this, arguments);\n }, iterator, callback);\n };\n\n async.until = function (test, iterator, callback) {\n return async.whilst(function() {\n return !test.apply(this, arguments);\n }, iterator, callback);\n };\n\n async.doUntil = function (iterator, test, callback) {\n return async.doWhilst(iterator, function() {\n return !test.apply(this, arguments);\n }, callback);\n };\n\n async.during = function (test, iterator, callback) {\n callback = callback || noop;\n\n var next = _restParam(function(err, args) {\n if (err) {\n callback(err);\n } else {\n args.push(check);\n test.apply(this, args);\n }\n });\n\n var check = function(err, truth) {\n if (err) {\n callback(err);\n } else if (truth) {\n iterator(next);\n } else {\n callback(null);\n }\n };\n\n test(check);\n };\n\n async.doDuring = function (iterator, test, callback) {\n var calls = 0;\n async.during(function(next) {\n if (calls++ < 1) {\n next(null, true);\n } else {\n test.apply(this, arguments);\n }\n }, iterator, callback);\n };\n\n function _queue(worker, concurrency, payload) {\n if (concurrency == null) {\n concurrency = 1;\n }\n else if(concurrency === 0) {\n throw new Error('Concurrency must not be zero');\n }\n function _insert(q, data, pos, callback) {\n if (callback != null && typeof callback !== \"function\") {\n throw new Error(\"task callback must be a function\");\n }\n q.started = true;\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length === 0 && q.idle()) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n q.drain();\n });\n }\n _arrayEach(data, function(task) {\n var item = {\n data: task,\n callback: callback || noop\n };\n\n if (pos) {\n q.tasks.unshift(item);\n } else {\n q.tasks.push(item);\n }\n\n if (q.tasks.length === q.concurrency) {\n q.saturated();\n }\n });\n async.setImmediate(q.process);\n }\n function _next(q, tasks) {\n return function(){\n workers -= 1;\n\n var removed = false;\n var args = arguments;\n _arrayEach(tasks, function (task) {\n _arrayEach(workersList, function (worker, index) {\n if (worker === task && !removed) {\n workersList.splice(index, 1);\n removed = true;\n }\n });\n\n task.callback.apply(task, args);\n });\n if (q.tasks.length + workers === 0) {\n q.drain();\n }\n q.process();\n };\n }\n\n var workers = 0;\n var workersList = [];\n var q = {\n tasks: [],\n concurrency: concurrency,\n payload: payload,\n saturated: noop,\n empty: noop,\n drain: noop,\n started: false,\n paused: false,\n push: function (data, callback) {\n _insert(q, data, false, callback);\n },\n kill: function () {\n q.drain = noop;\n q.tasks = [];\n },\n unshift: function (data, callback) {\n _insert(q, data, true, callback);\n },\n process: function () {\n while(!q.paused && workers < q.concurrency && q.tasks.length){\n\n var tasks = q.payload ?\n q.tasks.splice(0, q.payload) :\n q.tasks.splice(0, q.tasks.length);\n\n var data = _map(tasks, function (task) {\n return task.data;\n });\n\n if (q.tasks.length === 0) {\n q.empty();\n }\n workers += 1;\n workersList.push(tasks[0]);\n var cb = only_once(_next(q, tasks));\n worker(data, cb);\n }\n },\n length: function () {\n return q.tasks.length;\n },\n running: function () {\n return workers;\n },\n workersList: function () {\n return workersList;\n },\n idle: function() {\n return q.tasks.length + workers === 0;\n },\n pause: function () {\n q.paused = true;\n },\n resume: function () {\n if (q.paused === false) { return; }\n q.paused = false;\n var resumeCount = Math.min(q.concurrency, q.tasks.length);\n // Need to call q.process once per concurrent\n // worker to preserve full concurrency after pause\n for (var w = 1; w <= resumeCount; w++) {\n async.setImmediate(q.process);\n }\n }\n };\n return q;\n }\n\n async.queue = function (worker, concurrency) {\n var q = _queue(function (items, cb) {\n worker(items[0], cb);\n }, concurrency, 1);\n\n return q;\n };\n\n async.priorityQueue = function (worker, concurrency) {\n\n function _compareTasks(a, b){\n return a.priority - b.priority;\n }\n\n function _binarySearch(sequence, item, compare) {\n var beg = -1,\n end = sequence.length - 1;\n while (beg < end) {\n var mid = beg + ((end - beg + 1) >>> 1);\n if (compare(item, sequence[mid]) >= 0) {\n beg = mid;\n } else {\n end = mid - 1;\n }\n }\n return beg;\n }\n\n function _insert(q, data, priority, callback) {\n if (callback != null && typeof callback !== \"function\") {\n throw new Error(\"task callback must be a function\");\n }\n q.started = true;\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length === 0) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n q.drain();\n });\n }\n _arrayEach(data, function(task) {\n var item = {\n data: task,\n priority: priority,\n callback: typeof callback === 'function' ? callback : noop\n };\n\n q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);\n\n if (q.tasks.length === q.concurrency) {\n q.saturated();\n }\n async.setImmediate(q.process);\n });\n }\n\n // Start with a normal queue\n var q = async.queue(worker, concurrency);\n\n // Override push to accept second parameter representing priority\n q.push = function (data, priority, callback) {\n _insert(q, data, priority, callback);\n };\n\n // Remove unshift function\n delete q.unshift;\n\n return q;\n };\n\n async.cargo = function (worker, payload) {\n return _queue(worker, 1, payload);\n };\n\n function _console_fn(name) {\n return _restParam(function (fn, args) {\n fn.apply(null, args.concat([_restParam(function (err, args) {\n if (typeof console === 'object') {\n if (err) {\n if (console.error) {\n console.error(err);\n }\n }\n else if (console[name]) {\n _arrayEach(args, function (x) {\n console[name](x);\n });\n }\n }\n })]));\n });\n }\n async.log = _console_fn('log');\n async.dir = _console_fn('dir');\n /*async.info = _console_fn('info');\n async.warn = _console_fn('warn');\n async.error = _console_fn('error');*/\n\n async.memoize = function (fn, hasher) {\n var memo = {};\n var queues = {};\n var has = Object.prototype.hasOwnProperty;\n hasher = hasher || identity;\n var memoized = _restParam(function memoized(args) {\n var callback = args.pop();\n var key = hasher.apply(null, args);\n if (has.call(memo, key)) { \n async.setImmediate(function () {\n callback.apply(null, memo[key]);\n });\n }\n else if (has.call(queues, key)) {\n queues[key].push(callback);\n }\n else {\n queues[key] = [callback];\n fn.apply(null, args.concat([_restParam(function (args) {\n memo[key] = args;\n var q = queues[key];\n delete queues[key];\n for (var i = 0, l = q.length; i < l; i++) {\n q[i].apply(null, args);\n }\n })]));\n }\n });\n memoized.memo = memo;\n memoized.unmemoized = fn;\n return memoized;\n };\n\n async.unmemoize = function (fn) {\n return function () {\n return (fn.unmemoized || fn).apply(null, arguments);\n };\n };\n\n function _times(mapper) {\n return function (count, iterator, callback) {\n mapper(_range(count), iterator, callback);\n };\n }\n\n async.times = _times(async.map);\n async.timesSeries = _times(async.mapSeries);\n async.timesLimit = function (count, limit, iterator, callback) {\n return async.mapLimit(_range(count), limit, iterator, callback);\n };\n\n async.seq = function (/* functions... */) {\n var fns = arguments;\n return _restParam(function (args) {\n var that = this;\n\n var callback = args[args.length - 1];\n if (typeof callback == 'function') {\n args.pop();\n } else {\n callback = noop;\n }\n\n async.reduce(fns, args, function (newargs, fn, cb) {\n fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {\n cb(err, nextargs);\n })]));\n },\n function (err, results) {\n callback.apply(that, [err].concat(results));\n });\n });\n };\n\n async.compose = function (/* functions... */) {\n return async.seq.apply(null, Array.prototype.reverse.call(arguments));\n };\n\n\n function _applyEach(eachfn) {\n return _restParam(function(fns, args) {\n var go = _restParam(function(args) {\n var that = this;\n var callback = args.pop();\n return eachfn(fns, function (fn, _, cb) {\n fn.apply(that, args.concat([cb]));\n },\n callback);\n });\n if (args.length) {\n return go.apply(this, args);\n }\n else {\n return go;\n }\n });\n }\n\n async.applyEach = _applyEach(async.eachOf);\n async.applyEachSeries = _applyEach(async.eachOfSeries);\n\n\n async.forever = function (fn, callback) {\n var done = only_once(callback || noop);\n var task = ensureAsync(fn);\n function next(err) {\n if (err) {\n return done(err);\n }\n task(next);\n }\n next();\n };\n\n function ensureAsync(fn) {\n return _restParam(function (args) {\n var callback = args.pop();\n args.push(function () {\n var innerArgs = arguments;\n if (sync) {\n async.setImmediate(function () {\n callback.apply(null, innerArgs);\n });\n } else {\n callback.apply(null, innerArgs);\n }\n });\n var sync = true;\n fn.apply(this, args);\n sync = false;\n });\n }\n\n async.ensureAsync = ensureAsync;\n\n async.constant = _restParam(function(values) {\n var args = [null].concat(values);\n return function (callback) {\n return callback.apply(this, args);\n };\n });\n\n async.wrapSync =\n async.asyncify = function asyncify(func) {\n return _restParam(function (args) {\n var callback = args.pop();\n var result;\n try {\n result = func.apply(this, args);\n } catch (e) {\n return callback(e);\n }\n // if result is Promise object\n if (_isObject(result) && typeof result.then === \"function\") {\n result.then(function(value) {\n callback(null, value);\n })[\"catch\"](function(err) {\n callback(err.message ? err : new Error(err));\n });\n } else {\n callback(null, result);\n }\n });\n };\n\n // Node.js\n if (typeof module === 'object' && module.exports) {\n module.exports = async;\n }\n // AMD / RequireJS\n else if (typeof define === 'function' && define.amd) {\n define([], function () {\n return async;\n });\n }\n // included directly via