diff --git a/README.md b/README.md index 18fb1e3a7..f91a0aabc 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,7 @@ If you code with [TypeScript](http://www.typescriptlang.org/) there are comprehe * Documented how Phaser.Physics.P2.Body#addPolygon can mutate the `points` argument (#301). * Documented how `cacheAsBitmap` and `generateTexture` can trim transparent pixels (#283). * Deprecated Phaser.Device.isConsoleOpen. Now it always returns false. +* Moved addTouchLockCallback/removeTouchLockCallback from Phaser.Touch to Phaser.Input, it now also covers Phaser.MSPointer (#37) ### Bug Fixes @@ -310,10 +311,11 @@ If you code with [TypeScript](http://www.typescriptlang.org/) there are comprehe * Fixed movement of sprites with `fixedToCamera=true` when dragged by pointer (#297). * Fixed creature relative anchor points to be absolute (#288). * Fixed P2 Physics body not rotating shape (#258) +* Audio is now also unlocked for Chrome > 55, fixes audio not plaing in cross-origin iframe (#37) ### Thanks -@Aerolivier, @andrewjb123, @davvidbaker, @Formic, @fyyyyy, @Majirefy, @Plukers, @samid737, @samme, @tommitytom +@Aerolivier, @andrewjb123, @davvidbaker, @Formic, @fyyyyy, @Majirefy, @Plukers, @samid737, @samme, @tommitytom, @AleBles ## Version 2.8.3 - 21st July 2017 diff --git a/src/gameobjects/Video.js b/src/gameobjects/Video.js index 4174b300c..016d60d0b 100644 --- a/src/gameobjects/Video.js +++ b/src/gameobjects/Video.js @@ -641,7 +641,7 @@ Phaser.Video.prototype = { /** * Starts this video playing. - * + * * If the video is already playing, or has been queued to play with `changeSource` then this method just returns. * * @method Phaser.Video#play @@ -1055,7 +1055,7 @@ Phaser.Video.prototype = { */ setTouchLock: function () { - this.game.input.touch.addTouchLockCallback(this.unlock, this); + this.game.input.addTouchLockCallback(this.unlock, this); this.touchLocked = true; }, diff --git a/src/input/Input.js b/src/input/Input.js index bee5edb02..c79f4a66d 100644 --- a/src/input/Input.js +++ b/src/input/Input.js @@ -154,6 +154,15 @@ Phaser.Input = function (game) { */ this.recordLimit = 100; + /** + * An array of callbacks that will be fired every time a native touch start or touch end event (pointerdown or pointerup when using Pointer events) is received from the browser. + * This is used internally to handle audio and video unlocking on mobile devices. + * To add a callback to this array please use `Input.addTouchLockCallback`. + * @property {array} touchLockCallbacks + * @protected + */ + this.touchLockCallbacks = []; + /** * @property {Phaser.Pointer} pointer1 - A Pointer object. */ @@ -215,66 +224,66 @@ Phaser.Input = function (game) { /** * The most recently active Pointer object. - * + * * When you've limited max pointers to 1 this will accurately be either the first finger touched or mouse. - * + * * @property {Phaser.Pointer} activePointer */ this.activePointer = null; /** * The mouse has its own unique Phaser.Pointer object which you can use if making a desktop specific game. - * + * * @property {Pointer} mousePointer */ this.mousePointer = null; /** * The Mouse Input manager. - * - * You should not usually access this manager directly, but instead use Input.mousePointer or Input.activePointer + * + * You should not usually access this manager directly, but instead use Input.mousePointer or Input.activePointer * which normalizes all the input values for you, regardless of browser. - * + * * @property {Phaser.Mouse} mouse */ this.mouse = null; /** * The Keyboard Input manager. - * + * * @property {Phaser.Keyboard} keyboard */ this.keyboard = null; /** * The Touch Input manager. - * - * You should not usually access this manager directly, but instead use Input.activePointer + * + * You should not usually access this manager directly, but instead use Input.activePointer * which normalizes all the input values for you, regardless of browser. - * + * * @property {Phaser.Touch} touch */ this.touch = null; /** * The MSPointer Input manager. - * - * You should not usually access this manager directly, but instead use Input.activePointer + * + * You should not usually access this manager directly, but instead use Input.activePointer * which normalizes all the input values for you, regardless of browser. - * + * * @property {Phaser.MSPointer} mspointer */ this.mspointer = null; /** * The Gamepad Input manager. - * + * * @property {Phaser.Gamepad} gamepad */ this.gamepad = null; /** - * If the Input Manager has been reset locked then all calls made to InputManager.reset, + * If the Input Manager has been reset locked then all calls made to InputManager.reset, * such as from a State change, are ignored. * @property {boolean} resetLocked * @default @@ -486,13 +495,13 @@ Phaser.Input.prototype = { * selected then you can use this callback to do so. * * The callback will be sent 3 parameters: - * + * * 1) A reference to the Phaser.Pointer object that is processing the Items. * 2) An array containing all potential interactive candidates. This is an array of `InputHandler` objects, not Sprites. * 3) The current 'favorite' candidate, based on its priorityID and position in the display list. * * Your callback MUST return one of the candidates sent to it. - * + * * @method Phaser.Input#setInteractiveCandidateHandler * @param {function} callback - The callback that will be called each time `Pointer.processInteractiveObjects` is called. Set to `null` to disable. * @param {object} context - The context in which the callback will be called. @@ -508,17 +517,17 @@ Phaser.Input.prototype = { * Adds a callback that is fired every time the activePointer receives a DOM move event such as a mousemove or touchmove. * * The callback will be sent 4 parameters: - * + * * A reference to the Phaser.Pointer object that moved, * The x position of the pointer, * The y position, * A boolean indicating if the movement was the result of a 'click' event (such as a mouse click or touch down). - * + * * It will be called every time the activePointer moves, which in a multi-touch game can be a lot of times, so this is best * to only use if you've limited input to a single pointer (i.e. mouse or touch). - * + * * The callback is added to the Phaser.Input.moveCallbacks array and should be removed with Phaser.Input.deleteMoveCallback. - * + * * @method Phaser.Input#addMoveCallback * @param {function} callback - The callback that will be called each time the activePointer receives a DOM move event. * @param {object} context - The context in which the callback will be called. @@ -529,9 +538,58 @@ Phaser.Input.prototype = { }, + + /** + * Adds a callback that is fired when a browser touchstart or touchend event is received + * (pointerdown or pointerup when using pointer events). + * + * This is used internally to handle audio and video unlocking on mobile devices. + * + * If the callback returns 'true' then the callback is automatically deleted once invoked. + * + * The callback is added to the Phaser.Input.touchLockCallbacks array and should be removed with Phaser.Input.removeTouchLockCallback. + * + * @method Phaser.Touch#addTouchLockCallback + * @param {function} callback - The callback that will be called when a touchstart event is received. + * @param {object} context - The context in which the callback will be called. + * @param {boolean} [onEnd=false] - Will the callback fire on a touchstart (default) or touchend event? + */ + addTouchLockCallback: function (callback, context, onEnd) { + + if (onEnd === undefined) { onEnd = false; } + + this.touchLockCallbacks.push({ callback: callback, context: context, onEnd: onEnd }); + + }, + + /** + * Removes the callback at the defined index from the Phaser.Input.touchLockCallbacks array + * + * @method Phaser.Input#removeTouchLockCallback + * @param {function} callback - The callback to be removed. + * @param {object} context - The context in which the callback exists. + * @return {boolean} True if the callback was deleted, otherwise false. + */ + removeTouchLockCallback: function (callback, context) { + + var i = this.touchLockCallbacks.length; + + while (i--) + { + if (this.touchLockCallbacks[i].callback === callback && this.touchLockCallbacks[i].context === context) + { + this.touchLockCallbacks.splice(i, 1); + return true; + } + } + + return false; + + }, + /** * Removes the callback from the Phaser.Input.moveCallbacks array. - * + * * @method Phaser.Input#deleteMoveCallback * @param {function} callback - The callback to be removed. * @param {object} context - The context in which the callback exists. @@ -579,7 +637,7 @@ Phaser.Input.prototype = { /** * Updates the Input Manager. Called by the core Game loop. - * + * * @method Phaser.Input#update * @protected */ diff --git a/src/input/MSPointer.js b/src/input/MSPointer.js index 4558b1b1f..121a685ce 100644 --- a/src/input/MSPointer.js +++ b/src/input/MSPointer.js @@ -10,7 +10,7 @@ * It will work only in Internet Explorer 10+ and Windows Store or Windows Phone 8 apps using JavaScript. * http://msdn.microsoft.com/en-us/library/ie/hh673557(v=vs.85).aspx * -* You should not normally access this class directly, but instead use a Phaser.Pointer object which +* You should not normally access this class directly, but instead use a Phaser.Pointer object which * normalises all game input for you including accurate button handling. * * Please note that at the current time of writing Phaser does not yet support chorded button interactions: @@ -192,12 +192,24 @@ Phaser.MSPointer.prototype = { /** * The function that handles the PointerDown event. - * + * * @method Phaser.MSPointer#onPointerDown * @param {PointerEvent} event - The native DOM event. */ onPointerDown: function (event) { + var i = this.game.input.touchLockCallbacks.length; + + while (i--) + { + var cb = this.game.input.touchLockCallbacks[i]; + + if (!cb.onEnd && cb.callback.call(cb.context, this, event)) + { + this.game.input.touchLockCallbacks.splice(i, 1); + } + } + this.event = event; if (this.capture) @@ -272,6 +284,18 @@ Phaser.MSPointer.prototype = { */ onPointerUp: function (event) { + var i = this.game.input.touchLockCallbacks.length; + + while (i--) + { + var cb = this.game.input.touchLockCallbacks[i]; + + if (cb.onEnd && cb.callback.call(cb.context, this, event)) + { + this.game.input.touchLockCallbacks.splice(i, 1); + } + } + this.event = event; if (this.capture) @@ -304,7 +328,7 @@ Phaser.MSPointer.prototype = { /** * The internal method that handles the mouse up event from the window. - * + * * @method Phaser.MSPointer#onPointerUpGlobal * @param {PointerEvent} event - The native event from the browser. This gets stored in MSPointer.event. */ diff --git a/src/input/Touch.js b/src/input/Touch.js index 153084b7d..0ea7537ad 100644 --- a/src/input/Touch.js +++ b/src/input/Touch.js @@ -27,15 +27,6 @@ Phaser.Touch = function (game) { */ this.enabled = true; - /** - * An array of callbacks that will be fired every time a native touch start or touch end event is received from the browser. - * This is used internally to handle audio and video unlocking on mobile devices. - * To add a callback to this array please use `Touch.addTouchLockCallback`. - * @property {array} touchLockCallbacks - * @protected - */ - this.touchLockCallbacks = []; - /** * @property {object} callbackContext - The context under which callbacks are called. */ @@ -197,53 +188,6 @@ Phaser.Touch.prototype = { }, - /** - * Adds a callback that is fired when a browser touchstart or touchend event is received. - * - * This is used internally to handle audio and video unlocking on mobile devices. - * - * If the callback returns 'true' then the callback is automatically deleted once invoked. - * - * The callback is added to the Phaser.Touch.touchLockCallbacks array and should be removed with Phaser.Touch.removeTouchLockCallback. - * - * @method Phaser.Touch#addTouchLockCallback - * @param {function} callback - The callback that will be called when a touchstart event is received. - * @param {object} context - The context in which the callback will be called. - * @param {boolean} [onEnd=false] - Will the callback fire on a touchstart (default) or touchend event? - */ - addTouchLockCallback: function (callback, context, onEnd) { - - if (onEnd === undefined) { onEnd = false; } - - this.touchLockCallbacks.push({ callback: callback, context: context, onEnd: onEnd }); - - }, - - /** - * Removes the callback at the defined index from the Phaser.Touch.touchLockCallbacks array - * - * @method Phaser.Touch#removeTouchLockCallback - * @param {function} callback - The callback to be removed. - * @param {object} context - The context in which the callback exists. - * @return {boolean} True if the callback was deleted, otherwise false. - */ - removeTouchLockCallback: function (callback, context) { - - var i = this.touchLockCallbacks.length; - - while (i--) - { - if (this.touchLockCallbacks[i].callback === callback && this.touchLockCallbacks[i].context === context) - { - this.touchLockCallbacks.splice(i, 1); - return true; - } - } - - return false; - - }, - /** * The internal method that handles the touchstart event from the browser. * @method Phaser.Touch#onTouchStart @@ -251,15 +195,15 @@ Phaser.Touch.prototype = { */ onTouchStart: function (event) { - var i = this.touchLockCallbacks.length; + var i = this.game.input.touchLockCallbacks.length; while (i--) { - var cb = this.touchLockCallbacks[i]; + var cb = this.game.input.touchLockCallbacks[i]; if (!cb.onEnd && cb.callback.call(cb.context, this, event)) { - this.touchLockCallbacks.splice(i, 1); + this.game.input.touchLockCallbacks.splice(i, 1); } } @@ -406,15 +350,15 @@ Phaser.Touch.prototype = { */ onTouchEnd: function (event) { - var i = this.touchLockCallbacks.length; + var i = this.game.input.touchLockCallbacks.length; while (i--) { - var cb = this.touchLockCallbacks[i]; + var cb = this.game.input.touchLockCallbacks[i]; if (cb.onEnd && cb.callback.call(cb.context, this, event)) { - this.touchLockCallbacks.splice(i, 1); + this.game.input.touchLockCallbacks.splice(i, 1); } } diff --git a/src/sound/SoundManager.js b/src/sound/SoundManager.js index bd3ff53b6..7e62545bb 100644 --- a/src/sound/SoundManager.js +++ b/src/sound/SoundManager.js @@ -99,7 +99,7 @@ Phaser.SoundManager = function (game) { * Set to true to have all sound muted when the Phaser game pauses (such as on loss of focus), * or set to false to keep audio playing, regardless of the game pause state. You may need to * do this should you wish to control audio muting via external DOM buttons or similar. - * @property {boolean} muteOnPause + * @property {boolean} muteOnPause * @default */ this.muteOnPause = true; @@ -132,6 +132,7 @@ Phaser.SoundManager = function (game) { */ this._volume = 1; + /** * @property {array} _sounds - An array containing all the sounds * @private @@ -259,7 +260,7 @@ Phaser.SoundManager.prototype = { if (!this.noAudio) { // On mobile we need a native touch event before we can play anything, so capture it here - if (!this.game.device.cocoonJS && this.game.device.iOS || (window['PhaserGlobal'] && window['PhaserGlobal'].fakeiOSTouchLock)) + if (!this.game.device.cocoonJS && (this.game.device.android || this.game.device.iOS || (window['PhaserGlobal'] && window['PhaserGlobal'].fakeiOSTouchLock))) { this.setTouchLock(); } @@ -280,13 +281,13 @@ Phaser.SoundManager.prototype = { return; } - if (this.game.device.iOSVersion > 8) + if (this.game.device.iOSVersion > 8 || this.game.device.chromeVersion >= 55) { - this.game.input.touch.addTouchLockCallback(this.unlock, this, true); + this.game.input.addTouchLockCallback(this.unlock, this, true); } else { - this.game.input.touch.addTouchLockCallback(this.unlock, this); + this.game.input.addTouchLockCallback(this.unlock, this); } this.touchLocked = true; @@ -330,6 +331,11 @@ Phaser.SoundManager.prototype = { { this._unlockSource.start(0); } + + //This fixes locked audio in Chrome > 55 cross origin iframes + if (this._unlockSource.context.state === 'suspended') { + this._unlockSource.context.resume(); + } } // We can remove the event because we've done what we needed (started the unlock sound playing)