diff --git a/README.md b/README.md index d6d0ff52..99652292 100644 --- a/README.md +++ b/README.md @@ -46,12 +46,12 @@ Version 1.1.3 - in build * New: Added a new in-built texture. Sprites now use __default if no texture was provided (a 32x32 transparent PNG) or __missing if one was given but not found (a 32x32 black box with a green cross through it) * New: Added Phaser.Filter. A new way to use the new WebGL shaders/filters that the new version of Pixi supports. * New: The object returned by Math.sinCosGenerator now contains a length property. -* New: Phaser.BitmapData object. Can be used as a texture for a Sprite or Tiling Sprite. See the new examples and docs for details. +* New: Phaser.BitmapData object. A Canvas you can freely draw to with lots of functions. Can be used as a texture for Sprites. See the new examples and docs for details. * New: RenderTexture.render now takes a Phaser.Group. Also added renderXY for when you don't want to make a new Point object. -* New: Implementing PluginManager.remove, added PluginManager.removeAll (thanks crazysam) -* New: Added scrollFactorX/scrollFactorY to TilemapLayers (thanks jcd-as) +* New: PluginManager.remove, added PluginManager.removeAll (thanks crazysam) +* New: scrollFactorX/scrollFactorY have been added to TilemapLayers (thanks jcd-as) * New: Phaser.Game parent can now be an HTMLElement or a string (thanks beeglebug) -* New: Updated to use the latest version of Pixi.js - which means you can now use all the sexy new WebGL filters they added :) +* New: Now using the latest version of Pixi.js. Which means you can use all the sexy new WebGL filters :) * New: Sprite.animations.getAnimation will return an animation instance which was added by name. * New: Added Mouse.button which is set to the button that was pressed: Phaser.Mouse.LEFT_BUTTON, MIDDLE_BUTTON or RIGHT_BUTTON (thanks wKLV) * New: Added Mouse.pointerLock signal which you can listen to whenever the browser enters or leaves pointer lock mode. @@ -64,6 +64,8 @@ Version 1.1.3 - in build * New: Device.littleEndian boolean added. Only safe to use if the browser supports TypedArrays (which IE9 doesn't, but nearly all others do) * New: You can now call game.sound.play() and simply pass it a key. The sound will play if the audio system is unlocked and optionally destroy itself on complete. * New: Mouse.capture is a boolean. If set to true then DOM mouse events will have event.preventDefault() applied, if false they will propogate fully. +* New: Added Sound.externalNode which allows you to connect a Sound to an external node input rather than the SoundManager gain node. +* New: Added SoundManager.connectToMaster boolean. Used in conjunction with Sound.externalNode you can easily configure audio nodes to connect together for special effects. * Fixed: Lots of fixes to the TypeScript definitions file (many thanks gltovar) * Fixed: Tilemap commands use specified layer when one given (thanks Izzimach) @@ -77,6 +79,8 @@ Version 1.1.3 - in build * Fixed: Fixes to Math and Loader (thanks theJare) * Fixed: Tween - isRunning not reset when non-looped tween completes (thanks crazysam + kevinthompson) * Fixed: Math.normalizeAngle and Math.wrapAngle (thanks theJare) +* Fixed: Device.isTouch modified to test maxTouchPointers instead of MSPointer. +* Fixed: InputHandler.checkPointerOver now checks the visible status of the Sprite Group before processing. * Updated: ArcadePhysics.updateMotion applies the dt to the velocity calculations as well as position now (thanks jcs) * Updated: RequestAnimationFrame now retains the callbackID which is passed to cancelRequestAnimationFrame. diff --git a/build/config.php b/build/config.php index 07d864a9..04991d46 100644 --- a/build/config.php +++ b/build/config.php @@ -28,23 +28,7 @@ - - - - - - - - - - - - - - - - diff --git a/filters/Tunnel.js b/filters/Tunnel.js index d7fc4680..ba75b49d 100644 --- a/filters/Tunnel.js +++ b/filters/Tunnel.js @@ -8,7 +8,7 @@ Phaser.Filter.Tunnel = function (game) { this.uniforms.alpha = { type: '1f', value: 1 } this.uniforms.origin = { type: '1f', value: 2.0 } - this.uniforms.iChannel0 = { type: 'sampler2D', value: null, wrap: 'repeat' } + this.uniforms.iChannel0 = { type: 'sampler2D', value: null, repeat: true } this.fragmentSrc = [ diff --git a/src/core/Group.js b/src/core/Group.js index ba0cd61c..bc57be0e 100644 --- a/src/core/Group.js +++ b/src/core/Group.js @@ -1190,15 +1190,25 @@ Phaser.Group.prototype = { * * @method Phaser.Group#remove * @param {Any} child - The child to remove. + * @return {boolean} true if the child was removed from this Group, otherwise false. */ remove: function (child) { + if (child.group !== this) + { + return false; + } + if (child.events) { child.events.onRemovedFromGroup.dispatch(child, this); } - this._container.removeChild(child); + // Check it's actually in the container + if (child.parent === this._container) + { + this._container.removeChild(child); + } if (this.cursor == child) { @@ -1214,6 +1224,8 @@ Phaser.Group.prototype = { child.group = null; + return true; + }, /** diff --git a/src/gameobjects/GameObjectFactory.js b/src/gameobjects/GameObjectFactory.js index a69a7c8b..ae4f3382 100644 --- a/src/gameobjects/GameObjectFactory.js +++ b/src/gameobjects/GameObjectFactory.js @@ -104,13 +104,14 @@ Phaser.GameObjectFactory.prototype = { * * @method Phaser.GameObjectFactory#audio * @param {string} key - The Game.cache key of the sound that this object will use. - * @param {number} volume - The volume at which the sound will be played. - * @param {boolean} loop - Whether or not the sound will loop. + * @param {number} [volume=1] - The volume at which the sound will be played. + * @param {boolean} [loop=false] - Whether or not the sound will loop. + * @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio. * @return {Phaser.Sound} The newly created text object. */ - audio: function (key, volume, loop) { + audio: function (key, volume, loop, connect) { - return this.game.sound.add(key, volume, loop); + return this.game.sound.add(key, volume, loop, connect); }, diff --git a/src/input/InputHandler.js b/src/input/InputHandler.js index 85e411c9..5bcdd291 100644 --- a/src/input/InputHandler.js +++ b/src/input/InputHandler.js @@ -510,24 +510,24 @@ Phaser.InputHandler.prototype = { */ checkPointerOver: function (pointer) { - if (this.enabled && this.sprite.visible) + if (this.enabled === false || this.sprite.visible === false || (this.sprite.group && this.sprite.group.visible === false)) { - this.sprite.getLocalUnmodifiedPosition(this._tempPoint, pointer.x, pointer.y); - - if (this._tempPoint.x >= 0 && this._tempPoint.x <= this.sprite.currentFrame.width && this._tempPoint.y >= 0 && this._tempPoint.y <= this.sprite.currentFrame.height) - { - if (this.pixelPerfect) - { - return this.checkPixel(this._tempPoint.x, this._tempPoint.y); - } - else - { - return true; - } - } + return false; } - return false; + this.sprite.getLocalUnmodifiedPosition(this._tempPoint, pointer.x, pointer.y); + + if (this._tempPoint.x >= 0 && this._tempPoint.x <= this.sprite.currentFrame.width && this._tempPoint.y >= 0 && this._tempPoint.y <= this.sprite.currentFrame.height) + { + if (this.pixelPerfect) + { + return this.checkPixel(this._tempPoint.x, this._tempPoint.y); + } + else + { + return true; + } + } }, diff --git a/src/pixi/renderers/webgl/PixiShader.js b/src/pixi/renderers/webgl/PixiShader.js index 6af6f340..1dcbd714 100644 --- a/src/pixi/renderers/webgl/PixiShader.js +++ b/src/pixi/renderers/webgl/PixiShader.js @@ -31,8 +31,10 @@ PIXI.PixiShader = function() * @property {number} textureCount - A local texture counter for multi-texture shaders. */ this.textureCount = 0; + + // this.dirty = true; -} +}; /** * @method PIXI.PixiShader#init @@ -49,7 +51,7 @@ PIXI.PixiShader.prototype.init = function() this.uSampler = gl.getUniformLocation(program, "uSampler"); this.projectionVector = gl.getUniformLocation(program, "projectionVector"); this.offsetVector = gl.getUniformLocation(program, "offsetVector"); - // this.dimensions = gl.getUniformLocation(program, "dimensions"); + this.dimensions = gl.getUniformLocation(program, "dimensions"); // get and store the attributes this.aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); @@ -62,189 +64,80 @@ PIXI.PixiShader.prototype.init = function() // get the uniform locations.. this.uniforms[key].uniformLocation = gl.getUniformLocation(program, key); } + + this.initUniforms(); this.program = program; -} +}; /** -* Updates the shader uniform values. +* Initialises the shader uniform values. * Uniforms are specified in the GLSL_ES Specification: http://www.khronos.org/registry/webgl/specs/latest/1.0/ * http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf * -* @method PIXI.PixiShader#syncUniforms +* @method PIXI.PixiShader#initUniforms */ -PIXI.PixiShader.prototype.syncUniforms = function() +PIXI.PixiShader.prototype.initUniforms = function() { this.textureCount = 1; - var gl = PIXI.gl; + var uniform; for (var key in this.uniforms) { - var type = this.uniforms[key].type; - var transpose = false; + var uniform = this.uniforms[key]; + var type = uniform.type; - if (this.uniforms[key].transpose) + if (type == 'sampler2D') { - transpose = this.uniforms[key].transpose; - } - - if (type == "1f") - { - // void uniform1f(WebGLUniformLocation? location, GLfloat x); - gl.uniform1f(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "1fv") - { - // void uniform1fv(WebGLUniformLocation? location, Float32Array v); - // void uniform1fv(WebGLUniformLocation? location, sequence v); - gl.uniform1fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "1i") - { - // void uniform1i(WebGLUniformLocation? location, GLint x); - gl.uniform1i(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "1iv") - { - // void uniform1iv(WebGLUniformLocation? location, Int32Array v); - // void uniform1iv(WebGLUniformLocation? location, sequence v); - gl.uniform1i(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "2f") - { - // void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y); - gl.uniform2f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y); - } - else if (type == "2fv") - { - // void uniform2fv(WebGLUniformLocation? location, Float32Array v); - // void uniform2fv(WebGLUniformLocation? location, sequence v); - gl.uniform2fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "2i") - { - // void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); - gl.uniform2i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y); - } - else if (type == "2iv") - { - // void uniform2iv(WebGLUniformLocation? location, Int32Array v); - // void uniform2iv(WebGLUniformLocation? location, sequence v); - gl.uniform2iv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "3f") - { - // void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z); - gl.uniform3f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z); - } - else if (type == "3fv") - { - // void uniform3fv(WebGLUniformLocation? location, Float32Array v); - // void uniform3fv(WebGLUniformLocation? location, sequence v); - gl.uniform3fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "3i") - { - // void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); - gl.uniform3i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z); - } - else if (type == "3iv") - { - // void uniform3iv(WebGLUniformLocation? location, Int32Array v); - // void uniform3iv(WebGLUniformLocation? location, sequence v); - gl.uniform3iv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "4f") - { - // void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - gl.uniform4f(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z, this.uniforms[key].value.w); - } - else if (type == "4fv") - { - // void uniform4fv(WebGLUniformLocation? location, Float32Array v); - // void uniform4fv(WebGLUniformLocation? location, sequence v); - gl.uniform4fv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "4i") - { - // void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w); - gl.uniform4i(this.uniforms[key].uniformLocation, this.uniforms[key].value.x, this.uniforms[key].value.y, this.uniforms[key].value.z, this.uniforms[key].value.w); - } - else if (type == "4iv") - { - // void uniform4iv(WebGLUniformLocation? location, Int32Array v); - // void uniform4iv(WebGLUniformLocation? location, sequence v); - gl.uniform4iv(this.uniforms[key].uniformLocation, this.uniforms[key].value); - } - else if (type == "mat2") - { - // void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value); - // void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, sequence value); - gl.uniformMatrix2fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value); - } - else if (type == "mat3") - { - // void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value); - // void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, sequence value); - gl.uniformMatrix3fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value); - } - else if (type == "mat4") - { - // void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array value); - // void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, sequence value); - gl.uniformMatrix4fv(this.uniforms[key].uniformLocation, transpose, this.uniforms[key].value); - } - else if (type == "sampler2D") - { - if (this.uniforms[key].value && this.uniforms[key].value.baseTexture.hasLoaded) + if (uniform.value && uniform.value.baseTexture.hasLoaded) { - var texture = this.uniforms[key].value.baseTexture._glTexture; - var image = this.uniforms[key].value.baseTexture.source; - var format = gl.RGBA; + this.initSampler2D(uniform); + } + else + { + uniform._init = false; + } + } + else if (type == 'mat2' || type == 'mat3' || type == 'mat4') + { + // These require special handling + uniform.glMatrix = true; + uniform.glValueLength = 1; - if (this.uniforms[key].format && this.uniforms[key].format == 'luminance') - { - format = gl.LUMINANCE; - } + if (type == 'mat2') + { + uniform.glFunc = PIXI.gl.uniformMatrix2fv; + } + else if (type == 'mat3') + { + uniform.glFunc = PIXI.gl.uniformMatrix3fv; + } + else if (type == 'mat4') + { + uniform.glFunc = PIXI.gl.uniformMatrix4fv; + } + } + else + { + // GL function reference + uniform.glFunc = PIXI.gl['uniform' + type]; - gl.activeTexture(gl['TEXTURE' + this.textureCount]); - - if (this.uniforms[key].wrap) - { - if (this.uniforms[key].wrap == 'no-repeat' || this.uniforms[key].wrap === false) - { - this.createGLTextureLinear(gl, image, texture); - } - else if (this.uniforms[key].wrap == 'repeat' || this.uniforms[key].wrap === true) - { - this.createGLTexture(gl, image, format, texture); - } - else if (this.uniforms[key].wrap == 'nearest-repeat') - { - this.createGLTextureNearestRepeat(gl, image, texture); - } - else if (this.uniforms[key].wrap == 'nearest') - { - this.createGLTextureNearest(gl, image, texture); - } - else if (this.uniforms[key].wrap == 'audio') - { - this.createAudioTexture(gl, texture); - } - else if (this.uniforms[key].wrap == 'keyboard') - { - this.createKeyboardTexture(gl, texture); - } - } - else - { - this.createGLTextureLinear(gl, image, texture); - } - - gl.uniform1i(this.uniforms[key].uniformLocation, this.textureCount); - - this.textureCount++; + if (type == '2f' || type == '2i') + { + uniform.glValueLength = 2; + } + else if (type == '3f' || type == '3i') + { + uniform.glValueLength = 3; + } + else if (type == '4f' || type == '4i') + { + uniform.glValueLength = 4; + } + else + { + uniform.glValueLength = 1; } } } @@ -252,99 +145,100 @@ PIXI.PixiShader.prototype.syncUniforms = function() }; /** -* Binds the given texture and image data. The texture is set to REPEAT. -* Code based on Effects.js from ShaderToy.com -* @method PIXI.PixiShader#createGLTexture +* Initialises a Sampler2D uniform (which may only be available later on after initUniforms once the texture is has loaded) +* +* @method PIXI.PixiShader#initSampler2D */ -PIXI.PixiShader.prototype.createGLTexture = function(gl, image, format, texture) +PIXI.PixiShader.prototype.initSampler2D = function(uniform) { - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texImage2D(gl.TEXTURE_2D, 0, format, gl.RGBA, gl.UNSIGNED_BYTE, image); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - gl.generateMipmap(gl.TEXTURE_2D); -} + if (uniform.value && uniform.value.baseTexture.hasLoaded) + { + // GLTexture = mag linear, min linear_mipmap_linear, wrap repeat + gl.generateMipmap(gl.TEXTURE_2D); + // GLTextureLinear = mag/min linear, wrap clamp + // GLTextureNearestRepeat = mag/min NEAREST, wrap repeat + // GLTextureNearest = mag/min nearest, wrap clamp + // AudioTexture = whatever + luminance + + // magFilter can be: gl.LINEAR, gl.LINEAR_MIPMAP_LINEAR or gl.NEAREST + // wrapS/T can be: gl.CLAMP_TO_EDGE or gl.REPEAT + + var magFilter = (uniform.magFilter) ? uniform.magFilter : PIXI.gl.LINEAR; + var minFilter = (uniform.minFilter) ? uniform.minFilter : PIXI.gl.LINEAR; + var wrapS = (uniform.wrapS) ? uniform.wrapS : PIXI.gl.CLAMP_TO_EDGE; + var wrapT = (uniform.wrapT) ? uniform.wrapT : PIXI.gl.CLAMP_TO_EDGE; + var format = (uniform.luminance) ? PIXI.gl.LUMINANCE : PIXI.gl.RGBA; + + if (uniform.repeat) + { + wrapS = PIXI.gl.REPEAT; + wrapT = PIXI.gl.REPEAT; + } + + PIXI.gl.activeTexture(PIXI.gl['TEXTURE' + this.textureCount]); + PIXI.gl.bindTexture(PIXI.gl.TEXTURE_2D, uniform.value.baseTexture._glTexture); + PIXI.gl.pixelStorei(PIXI.gl.UNPACK_FLIP_Y_WEBGL, false); + + PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, format, PIXI.gl.RGBA, PIXI.gl.UNSIGNED_BYTE, uniform.value.baseTexture.source); + // PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, PIXI.gl.LUMINANCE, 512, 2, 0, PIXI.gl.LUMINANCE, PIXI.gl.UNSIGNED_BYTE, null); + // PIXI.gl.texImage2D(PIXI.gl.TEXTURE_2D, 0, PIXI.gl.LUMINANCE, 256, 2, 0, PIXI.gl.LUMINANCE, PIXI.gl.UNSIGNED_BYTE, null); + + PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_MAG_FILTER, magFilter); + PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_MIN_FILTER, minFilter); + PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_WRAP_S, wrapS); + PIXI.gl.texParameteri(PIXI.gl.TEXTURE_2D, PIXI.gl.TEXTURE_WRAP_T, wrapT); + + PIXI.gl.uniform1i(uniform.uniformLocation, this.textureCount); + + uniform._init = true; + + this.textureCount++; + } +}; /** -* Binds the given texture and image data. The texture is set to CLAMP_TO_EDGE. -* Code based on Effects.js from ShaderToy.com -* @method PIXI.PixiShader#createGLTextureLinear +* Updates the shader uniform values. +* +* @method PIXI.PixiShader#syncUniforms */ -PIXI.PixiShader.prototype.createGLTextureLinear = function(gl, image, texture) +PIXI.PixiShader.prototype.syncUniforms = function() { - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - 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); -} + var uniform; -/** -* Binds the given texture and image data. The texture is set to REPEAT with NEAREST. -* Code based on Effects.js from ShaderToy.com -* @method PIXI.PixiShader#createGLTextureNearestRepeat -*/ -PIXI.PixiShader.prototype.createGLTextureNearestRepeat = function(gl, image, texture) -{ - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); -} + // This would probably be faster in an array and it would guarantee key order + for (var key in this.uniforms) + { + uniform = this.uniforms[key]; -/** -* Binds the given texture and image data. The texture is set to CLAMP_TO_EDGE with NEAREST. -* Code based on Effects.js from ShaderToy.com -* @method PIXI.PixiShader#createGLTextureNearest -*/ -PIXI.PixiShader.prototype.createGLTextureNearest = function(gl, image, texture) -{ - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - 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); -} - -/** -* Binds the given texture data. The texture is set to CLAMP_TO_EDGE with LUMINANCE. Designed for use with real-time audio data. -* Code based on Effects.js from ShaderToy.com -* @method PIXI.PixiShader#createAudioTexture -*/ -PIXI.PixiShader.prototype.createAudioTexture = function(gl, texture) -{ - gl.bindTexture(gl.TEXTURE_2D, texture ); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR ); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR ); - 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) ; - gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 512, 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, null); -} - -/** -* Binds the given texture data. The texture is set to CLAMP_TO_EDGE with LUMINANCE. Designed for use with keyboard input data. -* Code based on Effects.js from ShaderToy.com -* @method PIXI.PixiShader#createKeyboardTexture -*/ -PIXI.PixiShader.prototype.createKeyboardTexture = function(gl, texture) -{ - gl.bindTexture(gl.TEXTURE_2D, texture ); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); - 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) ; - gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 256, 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, null); -} + if (uniform.glValueLength == 1) + { + if (uniform.glMatrix === true) + { + uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.transpose, uniform.value); + } + else + { + uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value); + } + } + else if (uniform.glValueLength == 2) + { + uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y); + } + else if (uniform.glValueLength == 3) + { + uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z); + } + else if (uniform.glValueLength == 4) + { + uniform.glFunc.call(PIXI.gl, uniform.uniformLocation, uniform.value.x, uniform.value.y, uniform.value.z, uniform.value.w); + } + else if (uniform.type == 'sampler2D' && uniform._init == false && uniform.value && uniform.value.baseTexture.hasLoaded === false) + { + this.initSampler2D(uniform); + } + } + +}; PIXI.PixiShader.defaultVertexSrc = [ diff --git a/src/sound/Sound.js b/src/sound/Sound.js index 7c7a48a0..4fe74531 100644 --- a/src/sound/Sound.js +++ b/src/sound/Sound.js @@ -15,10 +15,11 @@ * @param {number} [volume=1] - Default value for the volume, between 0 and 1. * @param {boolean} [loop=false] - Whether or not the sound will loop. */ -Phaser.Sound = function (game, key, volume, loop) { +Phaser.Sound = function (game, key, volume, loop, connect) { if (typeof volume == 'undefined') { volume = 1; } if (typeof loop == 'undefined') { loop = false; } + if (typeof connect === 'undefined') { connect = game.sound.connectToMaster; } /** * A reference to the currently running Game. @@ -152,6 +153,11 @@ Phaser.Sound = function (game, key, volume, loop) { */ this.usingAudioTag = this.game.sound.usingAudioTag; + /** + * @property {object} externalNode - If defined this Sound won't connect to the SoundManager master gain node, but will instead connect to externalNode.input. + */ + this.externalNode = null; + if (this.usingWebAudio) { this.context = this.game.sound.context; @@ -167,7 +173,11 @@ Phaser.Sound = function (game, key, volume, loop) { } this.gainNode.gain.value = volume * this.game.sound.volume; - this.gainNode.connect(this.masterGainNode); + + if (connect) + { + this.gainNode.connect(this.masterGainNode); + } } else { @@ -477,7 +487,16 @@ Phaser.Sound.prototype = { this._sound = this.context.createBufferSource(); this._sound.buffer = this._buffer; - this._sound.connect(this.gainNode); + + if (this.externalNode) + { + this._sound.connect(this.externalNode.input); + } + else + { + this._sound.connect(this.gainNode); + } + this.totalDuration = this._sound.buffer.duration; if (this.duration === 0) diff --git a/src/sound/SoundManager.js b/src/sound/SoundManager.js index a01b9546..d8a41c8c 100644 --- a/src/sound/SoundManager.js +++ b/src/sound/SoundManager.js @@ -78,6 +78,12 @@ Phaser.SoundManager = function (game) { */ this.noAudio = false; + /** + * @property {boolean} connectToMaster - Used in conjunction with Sound.externalNode this allows you to stop a Sound node being connected to the SoundManager master gain node. + * @default + */ + this.connectToMaster = true; + /** * @property {boolean} touchLocked - true if the audio system is currently locked awaiting a touch event. * @default @@ -174,7 +180,6 @@ Phaser.SoundManager.prototype = { this.masterGain.connect(this.context.destination); } - }, /** @@ -324,14 +329,16 @@ Phaser.SoundManager.prototype = { * @param {string} key - Asset key for the sound. * @param {number} [volume=1] - Default value for the volume. * @param {boolean} [loop=false] - Whether or not the sound will loop. + * @param {boolean} [connect=true] - Controls if the created Sound object will connect to the master gainNode of the SoundManager when running under WebAudio. * @return {Phaser.Sound} The new sound instance. */ - add: function (key, volume, loop) { + add: function (key, volume, loop, connect) { if (typeof volume === 'undefined') { volume = 1; } if (typeof loop === 'undefined') { loop = false; } + if (typeof connect === 'undefined') { connect = this.connectToMaster; } - var sound = new Phaser.Sound(this.game, key, volume, loop); + var sound = new Phaser.Sound(this.game, key, volume, loop, connect); this._sounds.push(sound); diff --git a/src/system/Device.js b/src/system/Device.js index f189e86f..47a97d71 100644 --- a/src/system/Device.js +++ b/src/system/Device.js @@ -354,11 +354,11 @@ Phaser.Device.prototype = { this.worker = !!window['Worker']; - if ('ontouchstart' in document.documentElement || window.navigator.msPointerEnabled) { + if ('ontouchstart' in document.documentElement || (window.navigator.maxTouchPoints && window.navigator.maxTouchPoints > 1)) { this.touch = true; } - if (window.navigator.msPointerEnabled) { + if (window.navigator.msPointerEnabled || window.navigator.pointerEnabled) { this.mspointer = true; } diff --git a/src/utils/Debug.js b/src/utils/Debug.js index 18dfa3a9..48184bcc 100644 --- a/src/utils/Debug.js +++ b/src/utils/Debug.js @@ -307,7 +307,7 @@ Phaser.Utils.Debug.prototype = { /** * Renders the Pointer.circle object onto the stage in green if down or red if up along with debug text. - * @method Phaser.Utils.Debug#renderDebug + * @method Phaser.Utils.Debug#renderPointer * @param {Phaser.Pointer} pointer - Description. * @param {boolean} [hideIfUp=false] - Doesn't render the circle if the pointer is up. * @param {string} [downColor='rgba(0,255,0,0.5)'] - The color the circle is rendered in if down.