From 377ab5a4e9c7ef0ce1c36ca20b712973431986bd Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:03:04 +0100 Subject: [PATCH 001/115] Defined unlock method on BaseSoundManager class as both implementations use it --- src/sound/BaseSoundManager.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 14fa91548..8a5d45903 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -248,6 +248,17 @@ var BaseSoundManager = new Class({ }); this.emit('stopall', this); }, + /** + * Method used internally for unlocking audio playback on devices that + * require user interaction before any sound can be played on a web page. + * + * Read more about how this issue is handled here in [this article](TODO add link). + * + * @override + * @protected + * @method Phaser.Sound.BaseSoundManager#unlock + */ + unlock: NOOP, /** * Method used internally for pausing sound manager if * Phaser.Sound.BaseSoundManager#pauseOnBlur is set to true. From b33af6d2aa7c0cdd079113372baea039eb452f7d Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:03:34 +0100 Subject: [PATCH 002/115] Calling unlock method in BaseSoundManager class constructor --- src/sound/BaseSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 8a5d45903..10d7b0a29 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -98,6 +98,7 @@ var BaseSoundManager = new Class({ * @default 0 */ this._detune = 0; + this.unlock(); }, /** * Adds a new sound into the sound manager. From 402aa27ff3a0ff1c48d0386d3ffc3db94d260308 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:05:35 +0100 Subject: [PATCH 003/115] Skipping setting preload attribute and events on an audio tag on mobile devices --- src/loader/filetypes/HTML5AudioFile.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index b6cd5eb2c..c8cb77118 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -74,12 +74,13 @@ var HTML5AudioFile = new Class({ var audio = new Audio(); audio.name = this.key + ('0' + i).slice(-2); // Useful for debugging audio.dataset.used = 'false'; - audio.preload = 'auto'; - // TODO check if ios is locked - - audio.oncanplaythrough = this.onProgress.bind(this); - audio.onerror = this.onError.bind(this); + if (!('ontouchstart' in window)) + { + audio.preload = 'auto'; + audio.oncanplaythrough = this.onProgress.bind(this); + audio.onerror = this.onError.bind(this); + } this.data.push(audio); } From ae36cf57291d0beac549e0ce06000f895e3c529f Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:06:46 +0100 Subject: [PATCH 004/115] Skipping calling load method on an audio tag on mobile devices --- src/loader/filetypes/HTML5AudioFile.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index c8cb77118..6fe57e5dc 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -69,13 +69,15 @@ var HTML5AudioFile = new Class({ this.filesLoaded = 0; this.percentComplete = 0; + var touchLocked = 'ontouchstart' in window; + for(var i = 0; i < instances; i++) { var audio = new Audio(); audio.name = this.key + ('0' + i).slice(-2); // Useful for debugging audio.dataset.used = 'false'; - if (!('ontouchstart' in window)) + if (!touchLocked) { audio.preload = 'auto'; audio.oncanplaythrough = this.onProgress.bind(this); @@ -89,7 +91,11 @@ var HTML5AudioFile = new Class({ { audio = this.data[i]; audio.src = GetURL(this, baseURL || ''); - audio.load(); + + if (!touchLocked) + { + audio.load(); + } } } From e75731df8753cc6ffd9725b755bd452dab11e0d0 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:07:50 +0100 Subject: [PATCH 005/115] Calling onLoad directly if device sound is locked since we are skipping actual loading --- src/loader/filetypes/HTML5AudioFile.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index 6fe57e5dc..2f11d9b3a 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -97,6 +97,11 @@ var HTML5AudioFile = new Class({ audio.load(); } } + + if (touchLocked) + { + this.onLoad(); + } } }); From 5720dff5dc385181e528a9d3c2908276a12950d6 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:08:38 +0100 Subject: [PATCH 006/115] onLoad needs to be called from timeout callback in order to not cause issues --- src/loader/filetypes/HTML5AudioFile.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index 2f11d9b3a..e4cbdda53 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -100,7 +100,11 @@ var HTML5AudioFile = new Class({ if (touchLocked) { - this.onLoad(); + setTimeout(function () + { + this.onLoad(); + + }.bind(this)); } } From 196018d04a917ac41688dc5acac9e127f8195672 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:09:20 +0100 Subject: [PATCH 007/115] Updating load progress properties when sound is locked --- src/loader/filetypes/HTML5AudioFile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index e4cbdda53..0e2de3a9d 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -102,6 +102,8 @@ var HTML5AudioFile = new Class({ { setTimeout(function () { + this.filesLoaded = this.filesTotal; + this.percentComplete = 1; this.onLoad(); }.bind(this)); From 5c118a3a94764fda517945367e5cf25bed5bcddc Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:10:03 +0100 Subject: [PATCH 008/115] audio tag does not support name attribute so setting that value to dataset --- src/loader/filetypes/HTML5AudioFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index 0e2de3a9d..4605fcb4a 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -74,7 +74,7 @@ var HTML5AudioFile = new Class({ for(var i = 0; i < instances; i++) { var audio = new Audio(); - audio.name = this.key + ('0' + i).slice(-2); // Useful for debugging + audio.dataset.name = this.key + ('0' + i).slice(-2); // Useful for debugging audio.dataset.used = 'false'; if (!touchLocked) From 4ca73ae3625e87d263a771018e17710b4ae90b0c Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:10:54 +0100 Subject: [PATCH 009/115] Removing unlock call since it is now done in BaseSoundManager class --- src/sound/webaudio/WebAudioSoundManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/webaudio/WebAudioSoundManager.js b/src/sound/webaudio/WebAudioSoundManager.js index 4d101da89..d19c48160 100644 --- a/src/sound/webaudio/WebAudioSoundManager.js +++ b/src/sound/webaudio/WebAudioSoundManager.js @@ -44,7 +44,6 @@ var WebAudioSoundManager = new Class({ * @property {AudioNode} destination */ this.destination = this.masterMuteNode; - this.unlock(); BaseSoundManager.call(this, game); }, /** @@ -81,6 +80,7 @@ var WebAudioSoundManager = new Class({ }, /** * Unlocks Web Audio API on iOS devices on the initial touch event. + * * Read more about how this issue is handled here in [this article](TODO add link). * * @private From f510f71213dd3d9928992f9bbbbe764734d43ae8 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:12:04 +0100 Subject: [PATCH 010/115] Implemented unlock method for HTML5AudioSoundManager class --- src/sound/html5/HTML5AudioSoundManager.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index e728a9e9e..98cb0637d 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -71,6 +71,23 @@ var HTML5AudioSoundManager = new Class({ this.sounds.push(sound); return sound; }, + unlock: function () { + var _this = this; + if ('ontouchstart' in window) { + var unlock_1 = function () { + document.body.removeEventListener('touchstart', unlock_1); + document.body.removeEventListener('touchend', unlock_1); + _this.game.cache.audio.entries.each(function (key, tags) { + for (var i = 0; i < tags.length; i++) { + tags[i].load(); + } + return true; + }); + }; + document.body.addEventListener('touchstart', unlock_1, false); + document.body.addEventListener('touchend', unlock_1, false); + } + }, onBlur: function () { this.forEachActiveSound(function (sound) { if (sound.isPlaying) { From 0b4a8b8b2d4ac77d4fb197821538138cefa6f698 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:13:13 +0100 Subject: [PATCH 011/115] Removed touchstart event listeners since they don't work for unlocking audio --- src/sound/html5/HTML5AudioSoundManager.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 98cb0637d..b73c789e6 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -75,7 +75,6 @@ var HTML5AudioSoundManager = new Class({ var _this = this; if ('ontouchstart' in window) { var unlock_1 = function () { - document.body.removeEventListener('touchstart', unlock_1); document.body.removeEventListener('touchend', unlock_1); _this.game.cache.audio.entries.each(function (key, tags) { for (var i = 0; i < tags.length; i++) { @@ -84,7 +83,6 @@ var HTML5AudioSoundManager = new Class({ return true; }); }; - document.body.addEventListener('touchstart', unlock_1, false); document.body.addEventListener('touchend', unlock_1, false); } }, From be7741ed8937025a86cf99f8744383c4b532d6c1 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 14:13:44 +0100 Subject: [PATCH 012/115] Resetting already started sounds before unlocking --- src/sound/html5/HTML5AudioSoundManager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index b73c789e6..07b6a3381 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -82,6 +82,10 @@ var HTML5AudioSoundManager = new Class({ } return true; }); + _this.forEachActiveSound(function (sound) { + sound.pause(); + sound.resume(); + }); }; document.body.addEventListener('touchend', unlock_1, false); } From 81f3b56b0adedcc5ea2f765507ac470c8c5a9c4f Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:01:50 +0100 Subject: [PATCH 013/115] Added touchLocked argument to HTML5AudioFile class constructor --- src/loader/filetypes/HTML5AudioFile.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index 4605fcb4a..6b73732ca 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -11,8 +11,10 @@ var HTML5AudioFile = new Class({ initialize: - function HTML5AudioFile (key, url, path, config) + function HTML5AudioFile (key, url, path, config, touchLocked) { + this.touchLocked = touchLocked; + var fileConfig = { type: 'audio', extension: GetFastValue(url, 'type', ''), From 541cd836881138c7f0ac9daf1b4fee2d16957055 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:04:06 +0100 Subject: [PATCH 014/115] Using object property instead of local var --- src/loader/filetypes/HTML5AudioFile.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index 6b73732ca..5cbe867bb 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -71,15 +71,13 @@ var HTML5AudioFile = new Class({ this.filesLoaded = 0; this.percentComplete = 0; - var touchLocked = 'ontouchstart' in window; - for(var i = 0; i < instances; i++) { var audio = new Audio(); audio.dataset.name = this.key + ('0' + i).slice(-2); // Useful for debugging audio.dataset.used = 'false'; - if (!touchLocked) + if (!this.touchLocked) { audio.preload = 'auto'; audio.oncanplaythrough = this.onProgress.bind(this); @@ -94,13 +92,13 @@ var HTML5AudioFile = new Class({ audio = this.data[i]; audio.src = GetURL(this, baseURL || ''); - if (!touchLocked) + if (!this.touchLocked) { audio.load(); } } - if (touchLocked) + if (this.touchLocked) { setTimeout(function () { From c4f4fbc79d5f852fc9cd1e8e72c12c21c3db6e03 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:04:55 +0100 Subject: [PATCH 015/115] Passing sound manager touchLocked value to HTML5AudioFile constructor --- src/loader/filetypes/AudioFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loader/filetypes/AudioFile.js b/src/loader/filetypes/AudioFile.js index 4e1dd28bd..4f48b09a3 100644 --- a/src/loader/filetypes/AudioFile.js +++ b/src/loader/filetypes/AudioFile.js @@ -83,7 +83,7 @@ AudioFile.create = function (loader, key, urls, config, xhrSettings) return new AudioFile(key, url, loader.path, xhrSettings, game.sound.context); } - return new HTML5AudioFile(key, url, loader.path, config); + return new HTML5AudioFile(key, url, loader.path, config, game.sound.touchLocked); }; // this.load.audio('sound', 'assets/audio/booom.ogg', config, xhrSettings); From 093f295389d9b5b5d217cf91d7ca2afcc35c5455 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:06:55 +0100 Subject: [PATCH 016/115] Added touchLockedActionQueue property to HTML5AudioSound class --- src/sound/html5/HTML5AudioSound.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index c6854d437..53339ce0c 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -44,6 +44,21 @@ var HTML5AudioSound = new Class({ * @default 0 */ this.previousTime = 0; + /** + * A queue of all actions performed on a sound object while audio was locked. + * Once the audio gets unlocked, after an explicit user interaction, + * all actions will be performed in chronological order. + * + * @private + * @property {{ + * sound: Phaser.Sound.HTML5AudioSound, + * type: string, + * name: string, + * value?: any, + * time: number, + * }[]} touchLockedActionQueue + */ + this.touchLockedActionQueue = manager.touchLocked ? [] : null; this.duration = this.tags[0].duration; this.totalDuration = this.tags[0].duration; BaseSound.call(this, manager, key, config); @@ -240,6 +255,19 @@ var HTML5AudioSound = new Class({ if (this.audio) { this.audio.playbackRate = this.totalRate; } + }, + checkTouchLocked: function (type, name, value) { + if (this.manager.touchLocked) { + this.touchLockedActionQueue.push({ + sound: this, + type: type, + name: name, + value: value, + time: window.performance.now() + }); + return true; + } + return false; } }); /** From 300ac5b8590a5262f7cc1ea566a7cd29d29b95d3 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:19:04 +0100 Subject: [PATCH 017/115] Using checkTouchLocked with play method --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 53339ce0c..61deee944 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -64,6 +64,9 @@ var HTML5AudioSound = new Class({ BaseSound.call(this, manager, key, config); }, play: function (markerName, config) { + if (this.checkTouchLocked('method', 'play', [markerName, config])) { + return false; + } if (!BaseSound.prototype.play.call(this, markerName, config)) { return false; } From 893882fe953ac6c35c1eacc0322891636f91c7bf Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:19:15 +0100 Subject: [PATCH 018/115] Using checkTouchLocked with pause method --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 61deee944..30002a097 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -78,6 +78,9 @@ var HTML5AudioSound = new Class({ return true; }, pause: function () { + if (this.checkTouchLocked('method', 'pause')) { + return false; + } if (this.startTime > 0) { return false; } From 796f3657acb42ed49e5433f28c07f01ee82843ba Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:19:25 +0100 Subject: [PATCH 019/115] Using checkTouchLocked with resume method --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 30002a097..bd855bc8f 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -95,6 +95,9 @@ var HTML5AudioSound = new Class({ return true; }, resume: function () { + if (this.checkTouchLocked('method', 'resume')) { + return false; + } if (this.startTime > 0) { return false; } From 22154ceace474b061a759cd477ad75358aab01c6 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:19:39 +0100 Subject: [PATCH 020/115] Using checkTouchLocked with stop method --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index bd855bc8f..1a0770068 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -112,6 +112,9 @@ var HTML5AudioSound = new Class({ return true; }, stop: function () { + if (this.checkTouchLocked('method', 'stop')) { + return false; + } if (!BaseSound.prototype.stop.call(this)) { return false; } From a9a3c3c2a240eb219f74ba5f99ebad7c73e7d740 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:20:44 +0100 Subject: [PATCH 021/115] Using checkTouchLocked with mute property --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 1a0770068..3baf58ff3 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -294,6 +294,9 @@ Object.defineProperty(HTML5AudioSound.prototype, 'mute', { }, set: function (value) { this.currentConfig.mute = value; + if (this.checkTouchLocked('property', 'mute', value)) { + return; + } this.setMute(); this.emit('mute', this, value); } From c2f7795a984b66342592faf43421003c047deb87 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:21:07 +0100 Subject: [PATCH 022/115] Using checkTouchLocked with volume property --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 3baf58ff3..c00d43b69 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -313,6 +313,9 @@ Object.defineProperty(HTML5AudioSound.prototype, 'volume', { }, set: function (value) { this.currentConfig.volume = value; + if (this.checkTouchLocked('property', 'volume', value)) { + return; + } this.setVolume(); this.emit('volume', this, value); } From 865f8d06ada468263d467cf7f1097a967e3c3fdc Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:22:03 +0100 Subject: [PATCH 023/115] Defined rate property setter to be able to use checkTouchLocked with it --- src/sound/html5/HTML5AudioSound.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index c00d43b69..8a6dc2e1d 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -320,6 +320,21 @@ Object.defineProperty(HTML5AudioSound.prototype, 'volume', { this.emit('volume', this, value); } }); +/** + * Playback rate. + * + * @name Phaser.Sound.HTML5AudioSound#rate + * @property {number} rate + */ +Object.defineProperty(HTML5AudioSound.prototype, 'rate', { + set: function (value) { + this.currentConfig.rate = value; + if (this.checkTouchLocked('property', 'rate', value)) { + return; + } + Object.getOwnPropertyDescriptor(BaseSound.prototype, 'rate').set.call(this, value); + } +}); /** * Current position of playing sound. * From eb5be4c75d5aa87b863a7e672b336fda59ece2d8 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:22:30 +0100 Subject: [PATCH 024/115] Defined detune property setter to be able to use checkTouchLocked with it --- src/sound/html5/HTML5AudioSound.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 8a6dc2e1d..0c5707e4c 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -335,6 +335,21 @@ Object.defineProperty(HTML5AudioSound.prototype, 'rate', { Object.getOwnPropertyDescriptor(BaseSound.prototype, 'rate').set.call(this, value); } }); +/** + * Detuning of sound. + * + * @name Phaser.Sound.HTML5AudioSound#detune + * @property {number} detune + */ +Object.defineProperty(HTML5AudioSound.prototype, 'detune', { + set: function (value) { + this.currentConfig.detune = value; + if (this.checkTouchLocked('property', 'detune', value)) { + return; + } + Object.getOwnPropertyDescriptor(BaseSound.prototype, 'detune').set.call(this, value); + } +}); /** * Current position of playing sound. * From 3ff214da5971c6f792c46782cca34f21b3451c3c Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:22:54 +0100 Subject: [PATCH 025/115] Defined rate property getter --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 0c5707e4c..1dde8fc53 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -327,6 +327,9 @@ Object.defineProperty(HTML5AudioSound.prototype, 'volume', { * @property {number} rate */ Object.defineProperty(HTML5AudioSound.prototype, 'rate', { + get: function () { + return Object.getOwnPropertyDescriptor(BaseSound.prototype, 'rate').get.call(this); + }, set: function (value) { this.currentConfig.rate = value; if (this.checkTouchLocked('property', 'rate', value)) { From 874b3d5bc19fcff4a57e9cdd227e54af35fb9476 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:23:04 +0100 Subject: [PATCH 026/115] Defined detune property getter --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 1dde8fc53..9b908f83b 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -345,6 +345,9 @@ Object.defineProperty(HTML5AudioSound.prototype, 'rate', { * @property {number} detune */ Object.defineProperty(HTML5AudioSound.prototype, 'detune', { + get: function () { + return Object.getOwnPropertyDescriptor(BaseSound.prototype, 'detune').get.call(this); + }, set: function (value) { this.currentConfig.detune = value; if (this.checkTouchLocked('property', 'detune', value)) { From 33bc3d8d5cbc66b17215ac9d538d5f70c472ae61 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:23:20 +0100 Subject: [PATCH 027/115] Using checkTouchLocked with seek property --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 9b908f83b..6c375274b 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -376,6 +376,9 @@ Object.defineProperty(HTML5AudioSound.prototype, 'seek', { } }, set: function (value) { + if (this.checkTouchLocked('property', 'seek', value)) { + return; + } if (this.startTime > 0) { return; } From 84a20395e6f939ddfdbc0a1f2eff9b676686827f Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:25:43 +0100 Subject: [PATCH 028/115] Using checkTouchLocked with loop property --- src/sound/html5/HTML5AudioSound.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 6c375274b..afb54afcb 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -408,6 +408,9 @@ Object.defineProperty(HTML5AudioSound.prototype, 'loop', { }, set: function (value) { this.currentConfig.loop = value; + if (this.checkTouchLocked('property', 'loop', value)) { + return; + } if (this.audio) { this.audio.loop = value; } From b9b5489ab3e8a096b2bc66274cbf8aec14f479fd Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:27:28 +0100 Subject: [PATCH 029/115] Added touchLocked property to HTML5AudioSoundManager class --- src/sound/html5/HTML5AudioSoundManager.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 07b6a3381..4866956f3 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -46,6 +46,14 @@ var HTML5AudioSoundManager = new Class({ * @default [] */ this.onBlurPausedSounds = []; + /** + * HTML5 Audio streams cannot be loaded unless triggered by explicit user interaction, such as a tap. + * True if the audio system is currently locked awaiting user interaction. + * + * @private + * @property {boolean} touchLocked + */ + this.touchLocked = 'ontouchstart' in window; /** * Property that actually holds the value of global mute * for HTML5 Audio sound manager implementation. From f52cfee58a37e9f1661d83133ac980002d45b381 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:27:59 +0100 Subject: [PATCH 030/115] Added touchUnlocked property to HTML5AudioSoundManager class --- src/sound/html5/HTML5AudioSoundManager.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 4866956f3..d4617e8da 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -54,6 +54,15 @@ var HTML5AudioSoundManager = new Class({ * @property {boolean} touchLocked */ this.touchLocked = 'ontouchstart' in window; + /** + * Flag used for indicating when the audio has been unlocked, + * if there ever was a need for it. + * + * @private + * @type {boolean} + * @default false + */ + this.touchUnlocked = false; /** * Property that actually holds the value of global mute * for HTML5 Audio sound manager implementation. From 38e59f6f4b835e15ae7d4f20658a3efd4baacb23 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:29:18 +0100 Subject: [PATCH 031/115] Using touchLocked value as condition --- src/sound/html5/HTML5AudioSoundManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index d4617e8da..fcb275d11 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -90,7 +90,7 @@ var HTML5AudioSoundManager = new Class({ }, unlock: function () { var _this = this; - if ('ontouchstart' in window) { + if (this.touchLocked) { var unlock_1 = function () { document.body.removeEventListener('touchend', unlock_1); _this.game.cache.audio.entries.each(function (key, tags) { From 644a28cb3c89f5a32caec8ce48ab18907207dcbc Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:31:01 +0100 Subject: [PATCH 032/115] Pushing all tags in an array before loading them --- src/sound/html5/HTML5AudioSoundManager.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index fcb275d11..07c760e5c 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -93,15 +93,15 @@ var HTML5AudioSoundManager = new Class({ if (this.touchLocked) { var unlock_1 = function () { document.body.removeEventListener('touchend', unlock_1); + var allTags = []; _this.game.cache.audio.entries.each(function (key, tags) { for (var i = 0; i < tags.length; i++) { - tags[i].load(); + allTags.push(tags[i]); } return true; }); - _this.forEachActiveSound(function (sound) { - sound.pause(); - sound.resume(); + allTags.forEach(function (tag) { + tag.load(); }); }; document.body.addEventListener('touchend', unlock_1, false); From 5916d9f423c410a9b93de6def0edc3de9e158349 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:31:56 +0100 Subject: [PATCH 033/115] Setting last audio tag event listener to set touchUnlocked when it is ready for playback --- src/sound/html5/HTML5AudioSoundManager.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 07c760e5c..4955eadbc 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -100,6 +100,11 @@ var HTML5AudioSoundManager = new Class({ } return true; }); + var lastTag = allTags[allTags.length - 1]; + lastTag.oncanplaythrough = function () { + lastTag.oncanplaythrough = null; + _this.touchUnlocked = true; + }; allTags.forEach(function (tag) { tag.load(); }); From dc3938e8ffb08aa70c03b415839171a61f242a1d Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:32:41 +0100 Subject: [PATCH 034/115] Added update method to handle unlocking --- src/sound/html5/HTML5AudioSoundManager.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 4955eadbc..00daf95ec 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -126,6 +126,13 @@ var HTML5AudioSoundManager = new Class({ }); this.onBlurPausedSounds.length = 0; }, + update: function () { + if (this.touchUnlocked) { + this.touchUnlocked = false; + this.touchLocked = false; + } + BaseSoundManager.prototype.update.call(this); + }, destroy: function () { BaseSoundManager.prototype.destroy.call(this); this.onBlurPausedSounds.length = 0; From d8e36615e790f85e45ce38e963b780d4fb6d7af3 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:35:08 +0100 Subject: [PATCH 035/115] Gathering all actions and performing them sequentially --- src/sound/html5/HTML5AudioSoundManager.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 00daf95ec..e76b82bee 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -130,6 +130,22 @@ var HTML5AudioSoundManager = new Class({ if (this.touchUnlocked) { this.touchUnlocked = false; this.touchLocked = false; + var allSoundsTouchLockedActionQueue_1 = []; + this.forEachActiveSound(function (sound) { + sound.touchLockedActionQueue.forEach(function (touchLockedAction) { + allSoundsTouchLockedActionQueue_1.push(touchLockedAction); + }); + }); + allSoundsTouchLockedActionQueue_1.forEach(function (touchLockedAction) { + switch (touchLockedAction.type) { + case 'method': + touchLockedAction.sound[touchLockedAction.name].apply(touchLockedAction.sound, touchLockedAction.value || []); + break; + case 'property': + touchLockedAction.sound[touchLockedAction.name] = touchLockedAction.value; + break; + } + }); } BaseSoundManager.prototype.update.call(this); }, From 04b9996ac7ce1e9eb97d140cddad9b7e50ce4a4e Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:35:33 +0100 Subject: [PATCH 036/115] Sorting actions to be performed in chronological order --- src/sound/html5/HTML5AudioSoundManager.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index e76b82bee..325c7ddc8 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -136,6 +136,9 @@ var HTML5AudioSoundManager = new Class({ allSoundsTouchLockedActionQueue_1.push(touchLockedAction); }); }); + allSoundsTouchLockedActionQueue_1.sort(function (tla1, tla2) { + return tla1.time - tla2.time; + }); allSoundsTouchLockedActionQueue_1.forEach(function (touchLockedAction) { switch (touchLockedAction.type) { case 'method': From 94cefc9621f081d1f3b60ba8cc4fe5e48dc69c7e Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 17:35:54 +0100 Subject: [PATCH 037/115] Resetting sound's touchLockedActionQueue --- src/sound/html5/HTML5AudioSoundManager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 325c7ddc8..0728694a6 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -135,6 +135,8 @@ var HTML5AudioSoundManager = new Class({ sound.touchLockedActionQueue.forEach(function (touchLockedAction) { allSoundsTouchLockedActionQueue_1.push(touchLockedAction); }); + sound.touchLockedActionQueue.length = 0; + sound.touchLockedActionQueue = null; }); allSoundsTouchLockedActionQueue_1.sort(function (tla1, tla2) { return tla1.time - tla2.time; From 31cd229bf2fda22ca8a9f9e5cc29ff91aee9f337 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:09:00 +0100 Subject: [PATCH 038/115] Added locked property to BaseSoundManager class --- src/sound/BaseSoundManager.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 10d7b0a29..b76e0f783 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -98,6 +98,16 @@ var BaseSoundManager = new Class({ * @default 0 */ this._detune = 0; + /** + * Mobile devices require sounds to be triggered from an explicit user action, + * such as a tap, before any sound can be loaded/played on a web page. + * Set to true if the audio system is currently locked awaiting user interaction. + * + * @readonly + * @property {boolean} locked + * @default false + */ + this.locked = false; this.unlock(); }, /** From 9ed999fada25d39bbec9c3e9dc8a1fc4bd6fe379 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:09:33 +0100 Subject: [PATCH 039/115] Calling unlocked method only if locked property is set to true --- src/sound/BaseSoundManager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index b76e0f783..bb1d6a0ca 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -108,7 +108,9 @@ var BaseSoundManager = new Class({ * @default false */ this.locked = false; - this.unlock(); + if (this.locked) { + this.unlock(); + } }, /** * Adds a new sound into the sound manager. From fbb1388f2d6ff8a58273cfe5628746df786adb38 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:10:40 +0100 Subject: [PATCH 040/115] Added unlocked property to BaseSoundManager class for internal use --- src/sound/BaseSoundManager.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index bb1d6a0ca..9a09778d9 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -108,6 +108,15 @@ var BaseSoundManager = new Class({ * @default false */ this.locked = false; + /** + * Flag used internally for handling when the audio system + * has been unlocked, if there ever was a need for it. + * + * @private + * @property {boolean} unlocked + * @default false + */ + this.unlocked = false; if (this.locked) { this.unlock(); } From 28b098348b401683b1e85f0f847d2c552ea8fff7 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:11:27 +0100 Subject: [PATCH 041/115] Handling unlocking in update method --- src/sound/BaseSoundManager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 9a09778d9..0027db8af 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -309,6 +309,10 @@ var BaseSoundManager = new Class({ * @param {number} delta - The delta time elapsed since the last frame. */ update: function (time, delta) { + if (this.unlocked) { + this.unlocked = false; + this.emit('unlocked', this); + } for (var i = this.sounds.length - 1; i >= 0; i--) { if (this.sounds[i].pendingRemove) { this.sounds.splice(i, 1); From 8ec82c3a4d51fdc41e7d93da707d65d2d7777e6d Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:12:03 +0100 Subject: [PATCH 042/115] Setting locked property to false after unlocking --- src/sound/BaseSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 0027db8af..6dbfcf410 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -311,6 +311,7 @@ var BaseSoundManager = new Class({ update: function (time, delta) { if (this.unlocked) { this.unlocked = false; + this.locked = false; this.emit('unlocked', this); } for (var i = this.sounds.length - 1; i >= 0; i--) { From a90760f8df5cbafebd6264254b80c8cae5c50860 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:13:04 +0100 Subject: [PATCH 043/115] Setting locked property for WebAudioSoundManager --- src/sound/webaudio/WebAudioSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/webaudio/WebAudioSoundManager.js b/src/sound/webaudio/WebAudioSoundManager.js index d19c48160..70335f200 100644 --- a/src/sound/webaudio/WebAudioSoundManager.js +++ b/src/sound/webaudio/WebAudioSoundManager.js @@ -44,6 +44,7 @@ var WebAudioSoundManager = new Class({ * @property {AudioNode} destination */ this.destination = this.masterMuteNode; + this.locked = this.context.state === 'suspended' && 'ontouchstart' in window; BaseSoundManager.call(this, game); }, /** From bf0c868bf38b166a65824ae47b369b71e5fb356a Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:13:52 +0100 Subject: [PATCH 044/115] Removed condition since it is already performed in base class constructor --- src/sound/webaudio/WebAudioSoundManager.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/sound/webaudio/WebAudioSoundManager.js b/src/sound/webaudio/WebAudioSoundManager.js index 70335f200..967bed6d4 100644 --- a/src/sound/webaudio/WebAudioSoundManager.js +++ b/src/sound/webaudio/WebAudioSoundManager.js @@ -89,16 +89,14 @@ var WebAudioSoundManager = new Class({ */ unlock: function () { var _this = this; - if (this.context.state === 'suspended' && 'ontouchstart' in window) { - var unlock_1 = function () { - _this.context.resume().then(function () { - document.body.removeEventListener('touchstart', unlock_1); - document.body.removeEventListener('touchend', unlock_1); - }); - }; - document.body.addEventListener('touchstart', unlock_1, false); - document.body.addEventListener('touchend', unlock_1, false); - } + var unlock = function () { + _this.context.resume().then(function () { + document.body.removeEventListener('touchstart', unlock); + document.body.removeEventListener('touchend', unlock); + }); + }; + document.body.addEventListener('touchstart', unlock, false); + document.body.addEventListener('touchend', unlock, false); }, /** * Method used internally for pausing sound manager if From c6c3f1da798d3425fd725ffa31937ae1701052ae Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:14:28 +0100 Subject: [PATCH 045/115] Setting unlocked property to true when audio context resumes --- src/sound/webaudio/WebAudioSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/webaudio/WebAudioSoundManager.js b/src/sound/webaudio/WebAudioSoundManager.js index 967bed6d4..c1e426ab4 100644 --- a/src/sound/webaudio/WebAudioSoundManager.js +++ b/src/sound/webaudio/WebAudioSoundManager.js @@ -93,6 +93,7 @@ var WebAudioSoundManager = new Class({ _this.context.resume().then(function () { document.body.removeEventListener('touchstart', unlock); document.body.removeEventListener('touchend', unlock); + _this.unlocked = true; }); }; document.body.addEventListener('touchstart', unlock, false); From 6b1b7a13424b36284d5cb99676a65ce85bc28e4b Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:15:50 +0100 Subject: [PATCH 046/115] Removed touchLocked property form HTML5AudioSoundManager class --- src/sound/html5/HTML5AudioSoundManager.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 0728694a6..1d3004284 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -46,14 +46,6 @@ var HTML5AudioSoundManager = new Class({ * @default [] */ this.onBlurPausedSounds = []; - /** - * HTML5 Audio streams cannot be loaded unless triggered by explicit user interaction, such as a tap. - * True if the audio system is currently locked awaiting user interaction. - * - * @private - * @property {boolean} touchLocked - */ - this.touchLocked = 'ontouchstart' in window; /** * Flag used for indicating when the audio has been unlocked, * if there ever was a need for it. From ff4e9616f338db411312f3a22502f87e249af35b Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:16:14 +0100 Subject: [PATCH 047/115] Removed touchUnlocked property form HTML5AudioSoundManager class --- src/sound/html5/HTML5AudioSoundManager.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 1d3004284..13765251b 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -46,15 +46,6 @@ var HTML5AudioSoundManager = new Class({ * @default [] */ this.onBlurPausedSounds = []; - /** - * Flag used for indicating when the audio has been unlocked, - * if there ever was a need for it. - * - * @private - * @type {boolean} - * @default false - */ - this.touchUnlocked = false; /** * Property that actually holds the value of global mute * for HTML5 Audio sound manager implementation. From 0f6f0ab45e0066ea85cb37e1701a707b0d787526 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:17:01 +0100 Subject: [PATCH 048/115] Setting locked property for HTML5AudioSoundManager class --- src/sound/html5/HTML5AudioSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 13765251b..2d1e3b860 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -64,6 +64,7 @@ var HTML5AudioSoundManager = new Class({ * @default 1 */ this._volume = 1; + this.locked = 'ontouchstart' in window; BaseSoundManager.call(this, game); }, add: function (key, config) { From fdbda3cffa73441a9210bfaeb707fef8e8de1ea8 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:17:31 +0100 Subject: [PATCH 049/115] Setting locked property to value set in subclass if available --- src/sound/BaseSoundManager.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 6dbfcf410..ab36167fd 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -105,9 +105,8 @@ var BaseSoundManager = new Class({ * * @readonly * @property {boolean} locked - * @default false */ - this.locked = false; + this.locked = this.locked || false; /** * Flag used internally for handling when the audio system * has been unlocked, if there ever was a need for it. From d388c827e416bbd12fc26fdb53c775cb06d7cbab Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:18:22 +0100 Subject: [PATCH 050/115] Added a TODO for setting correct duration value when available --- src/sound/html5/HTML5AudioSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 2d1e3b860..386d43189 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -121,6 +121,7 @@ var HTML5AudioSoundManager = new Class({ }); sound.touchLockedActionQueue.length = 0; sound.touchLockedActionQueue = null; + // TODO set correct duration value }); allSoundsTouchLockedActionQueue_1.sort(function (tla1, tla2) { return tla1.time - tla2.time; From 5f035c80e2fd5dcd91bbda6bdce17585636a3f88 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:19:26 +0100 Subject: [PATCH 051/115] Removed condition since it is already performed in base class constructor --- src/sound/html5/HTML5AudioSoundManager.js | 38 +++++++++++------------ 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 386d43189..a127acbfa 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -74,27 +74,25 @@ var HTML5AudioSoundManager = new Class({ }, unlock: function () { var _this = this; - if (this.touchLocked) { - var unlock_1 = function () { - document.body.removeEventListener('touchend', unlock_1); - var allTags = []; - _this.game.cache.audio.entries.each(function (key, tags) { - for (var i = 0; i < tags.length; i++) { - allTags.push(tags[i]); - } - return true; - }); - var lastTag = allTags[allTags.length - 1]; - lastTag.oncanplaythrough = function () { - lastTag.oncanplaythrough = null; - _this.touchUnlocked = true; - }; - allTags.forEach(function (tag) { - tag.load(); - }); + var unlock = function () { + document.body.removeEventListener('touchend', unlock); + var allTags = []; + _this.game.cache.audio.entries.each(function (key, tags) { + for (var i = 0; i < tags.length; i++) { + allTags.push(tags[i]); + } + return true; + }); + var lastTag = allTags[allTags.length - 1]; + lastTag.oncanplaythrough = function () { + lastTag.oncanplaythrough = null; + _this.touchUnlocked = true; }; - document.body.addEventListener('touchend', unlock_1, false); - } + allTags.forEach(function (tag) { + tag.load(); + }); + }; + document.body.addEventListener('touchend', unlock, false); }, onBlur: function () { this.forEachActiveSound(function (sound) { From fb52e3d4909f4f615523c8af8cb3ca847788cacd Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:19:51 +0100 Subject: [PATCH 052/115] Setting unlocked property to true when audio tags are ready --- src/sound/html5/HTML5AudioSoundManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index a127acbfa..2105083bf 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -86,7 +86,7 @@ var HTML5AudioSoundManager = new Class({ var lastTag = allTags[allTags.length - 1]; lastTag.oncanplaythrough = function () { lastTag.oncanplaythrough = null; - _this.touchUnlocked = true; + _this.unlocked = true; }; allTags.forEach(function (tag) { tag.load(); From bcb11d5c4e0cb82610c82cf281a5da019366418d Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 18:24:03 +0100 Subject: [PATCH 053/115] Moved queued sound actions logic from update method to unlocked event handler --- src/sound/html5/HTML5AudioSoundManager.js | 53 ++++++++++------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 2105083bf..a1067b12b 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -92,6 +92,30 @@ var HTML5AudioSoundManager = new Class({ tag.load(); }); }; + this.once('unlocked', function () { + var allSoundsTouchLockedActionQueue = []; + _this.forEachActiveSound(function (sound) { + sound.touchLockedActionQueue.forEach(function (touchLockedAction) { + allSoundsTouchLockedActionQueue.push(touchLockedAction); + }); + sound.touchLockedActionQueue.length = 0; + sound.touchLockedActionQueue = null; + // TODO set correct duration value + }); + allSoundsTouchLockedActionQueue.sort(function (tla1, tla2) { + return tla1.time - tla2.time; + }); + allSoundsTouchLockedActionQueue.forEach(function (touchLockedAction) { + switch (touchLockedAction.type) { + case 'method': + touchLockedAction.sound[touchLockedAction.name].apply(touchLockedAction.sound, touchLockedAction.value || []); + break; + case 'property': + touchLockedAction.sound[touchLockedAction.name] = touchLockedAction.value; + break; + } + }); + }); document.body.addEventListener('touchend', unlock, false); }, onBlur: function () { @@ -108,35 +132,6 @@ var HTML5AudioSoundManager = new Class({ }); this.onBlurPausedSounds.length = 0; }, - update: function () { - if (this.touchUnlocked) { - this.touchUnlocked = false; - this.touchLocked = false; - var allSoundsTouchLockedActionQueue_1 = []; - this.forEachActiveSound(function (sound) { - sound.touchLockedActionQueue.forEach(function (touchLockedAction) { - allSoundsTouchLockedActionQueue_1.push(touchLockedAction); - }); - sound.touchLockedActionQueue.length = 0; - sound.touchLockedActionQueue = null; - // TODO set correct duration value - }); - allSoundsTouchLockedActionQueue_1.sort(function (tla1, tla2) { - return tla1.time - tla2.time; - }); - allSoundsTouchLockedActionQueue_1.forEach(function (touchLockedAction) { - switch (touchLockedAction.type) { - case 'method': - touchLockedAction.sound[touchLockedAction.name].apply(touchLockedAction.sound, touchLockedAction.value || []); - break; - case 'property': - touchLockedAction.sound[touchLockedAction.name] = touchLockedAction.value; - break; - } - }); - } - BaseSoundManager.prototype.update.call(this); - }, destroy: function () { BaseSoundManager.prototype.destroy.call(this); this.onBlurPausedSounds.length = 0; From 19ec0fb7351dd2d2de0dcab410d0405ee18be530 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:02:10 +0100 Subject: [PATCH 054/115] Added lockedActionsQueue property to HTML5AudioSoundManager class for internal use --- src/sound/html5/HTML5AudioSoundManager.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index a1067b12b..776685201 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -46,6 +46,20 @@ var HTML5AudioSoundManager = new Class({ * @default [] */ this.onBlurPausedSounds = []; + /** + * A queue of all actions performed on sound objects while audio was locked. + * Once the audio gets unlocked, after an explicit user interaction, + * all actions will be performed in chronological order. + * + * @private + * @property {{ + * sound: Phaser.Sound.HTML5AudioSound, + * name: string, + * value?: any, + * }[]} lockedActionsQueue + * @default [] + */ + this.lockedActionsQueue = []; /** * Property that actually holds the value of global mute * for HTML5 Audio sound manager implementation. From aacd7a972df0e5f0eca15b1ce81a5d50eaf057d9 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:03:16 +0100 Subject: [PATCH 055/115] Setting lockedActionsQueue value based on locked property value --- src/sound/html5/HTML5AudioSoundManager.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 776685201..6588ec68e 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -46,6 +46,7 @@ var HTML5AudioSoundManager = new Class({ * @default [] */ this.onBlurPausedSounds = []; + this.locked = 'ontouchstart' in window; /** * A queue of all actions performed on sound objects while audio was locked. * Once the audio gets unlocked, after an explicit user interaction, @@ -57,9 +58,8 @@ var HTML5AudioSoundManager = new Class({ * name: string, * value?: any, * }[]} lockedActionsQueue - * @default [] */ - this.lockedActionsQueue = []; + this.lockedActionsQueue = this.locked ? [] : null; /** * Property that actually holds the value of global mute * for HTML5 Audio sound manager implementation. @@ -78,7 +78,6 @@ var HTML5AudioSoundManager = new Class({ * @default 1 */ this._volume = 1; - this.locked = 'ontouchstart' in window; BaseSoundManager.call(this, game); }, add: function (key, config) { From 88d26607ec5c95852c3012ea485774f5ee5d8160 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:07:52 +0100 Subject: [PATCH 056/115] Updated and simplified logic for performing locked actions --- src/sound/html5/HTML5AudioSoundManager.js | 26 ++++++----------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 6588ec68e..18bf3ea25 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -106,26 +106,12 @@ var HTML5AudioSoundManager = new Class({ }); }; this.once('unlocked', function () { - var allSoundsTouchLockedActionQueue = []; - _this.forEachActiveSound(function (sound) { - sound.touchLockedActionQueue.forEach(function (touchLockedAction) { - allSoundsTouchLockedActionQueue.push(touchLockedAction); - }); - sound.touchLockedActionQueue.length = 0; - sound.touchLockedActionQueue = null; - // TODO set correct duration value - }); - allSoundsTouchLockedActionQueue.sort(function (tla1, tla2) { - return tla1.time - tla2.time; - }); - allSoundsTouchLockedActionQueue.forEach(function (touchLockedAction) { - switch (touchLockedAction.type) { - case 'method': - touchLockedAction.sound[touchLockedAction.name].apply(touchLockedAction.sound, touchLockedAction.value || []); - break; - case 'property': - touchLockedAction.sound[touchLockedAction.name] = touchLockedAction.value; - break; + _this.lockedActionsQueue.forEach(function (lockedAction) { + if (lockedAction.sound[lockedAction.name].apply) { + lockedAction.sound[lockedAction.name].apply(lockedAction.sound, lockedAction.value || []); + } + else { + lockedAction.sound[lockedAction.name] = lockedAction.value; } }); }); From b25af58495b179cebb4e5f898d5ad9c1edf1fca5 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:09:36 +0100 Subject: [PATCH 057/115] Resetting lockedActionsQueue after performing all locked actions --- src/sound/html5/HTML5AudioSoundManager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 18bf3ea25..d9ab8a148 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -114,6 +114,8 @@ var HTML5AudioSoundManager = new Class({ lockedAction.sound[lockedAction.name] = lockedAction.value; } }); + _this.lockedActionsQueue.length = 0; + _this.lockedActionsQueue = null; }); document.body.addEventListener('touchend', unlock, false); }, From 913f388535188dc2a02c14e560e423e95cf2e8d3 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:10:24 +0100 Subject: [PATCH 058/115] Added isLocked method to handle locked actions --- src/sound/html5/HTML5AudioSoundManager.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index d9ab8a148..a6ca6eb28 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -137,6 +137,17 @@ var HTML5AudioSoundManager = new Class({ BaseSoundManager.prototype.destroy.call(this); this.onBlurPausedSounds.length = 0; this.onBlurPausedSounds = null; + }, + isLocked: function (sound, name, value) { + if (this.locked) { + this.lockedActionsQueue.push({ + sound: sound, + name: name, + value: value + }); + return true; + } + return false; } }); /** From da56f9758060a0800d41c35e41c660db72d4f72a Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:11:28 +0100 Subject: [PATCH 059/115] Removed touchLockedActionQueue from HTML5AudioSound class --- src/sound/html5/HTML5AudioSound.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index afb54afcb..7344ecef9 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -44,21 +44,6 @@ var HTML5AudioSound = new Class({ * @default 0 */ this.previousTime = 0; - /** - * A queue of all actions performed on a sound object while audio was locked. - * Once the audio gets unlocked, after an explicit user interaction, - * all actions will be performed in chronological order. - * - * @private - * @property {{ - * sound: Phaser.Sound.HTML5AudioSound, - * type: string, - * name: string, - * value?: any, - * time: number, - * }[]} touchLockedActionQueue - */ - this.touchLockedActionQueue = manager.touchLocked ? [] : null; this.duration = this.tags[0].duration; this.totalDuration = this.tags[0].duration; BaseSound.call(this, manager, key, config); From cee22b158cbe070d956c160bdb772474cd4853f0 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:11:50 +0100 Subject: [PATCH 060/115] Removed checkTouchLocked from HTML5AudioSound class --- src/sound/html5/HTML5AudioSound.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 7344ecef9..7ef233022 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -252,19 +252,6 @@ var HTML5AudioSound = new Class({ if (this.audio) { this.audio.playbackRate = this.totalRate; } - }, - checkTouchLocked: function (type, name, value) { - if (this.manager.touchLocked) { - this.touchLockedActionQueue.push({ - sound: this, - type: type, - name: name, - value: value, - time: window.performance.now() - }); - return true; - } - return false; } }); /** From ce6f3400e2c6eccf43e2f5e88d4e08a447eae6fb Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:13:09 +0100 Subject: [PATCH 061/115] Using manager.isLocked instead of removed checkTouchLocked method for play method --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 7ef233022..c3f419bc7 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -49,7 +49,7 @@ var HTML5AudioSound = new Class({ BaseSound.call(this, manager, key, config); }, play: function (markerName, config) { - if (this.checkTouchLocked('method', 'play', [markerName, config])) { + if (this.manager.isLocked(this, 'play', [markerName, config])) { return false; } if (!BaseSound.prototype.play.call(this, markerName, config)) { From fb775d4063ca431b55247a0c84717529f1eb3c3e Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:13:21 +0100 Subject: [PATCH 062/115] Using manager.isLocked instead of removed checkTouchLocked method for pause method --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index c3f419bc7..7429d1e95 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -63,7 +63,7 @@ var HTML5AudioSound = new Class({ return true; }, pause: function () { - if (this.checkTouchLocked('method', 'pause')) { + if (this.manager.isLocked(this, 'pause')) { return false; } if (this.startTime > 0) { From 5c0c89022e19ad29474b9450c802ace09b7b713c Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:13:36 +0100 Subject: [PATCH 063/115] Using manager.isLocked instead of removed checkTouchLocked method for resume method --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 7429d1e95..0122b79c9 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -80,7 +80,7 @@ var HTML5AudioSound = new Class({ return true; }, resume: function () { - if (this.checkTouchLocked('method', 'resume')) { + if (this.manager.isLocked(this, 'resume')) { return false; } if (this.startTime > 0) { From 4b6287c4cdb7ab58a88337b888503234fb7f337c Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:13:47 +0100 Subject: [PATCH 064/115] Using manager.isLocked instead of removed checkTouchLocked method for stop method --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 0122b79c9..837fca060 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -97,7 +97,7 @@ var HTML5AudioSound = new Class({ return true; }, stop: function () { - if (this.checkTouchLocked('method', 'stop')) { + if (this.manager.isLocked(this, 'stop')) { return false; } if (!BaseSound.prototype.stop.call(this)) { From 941b4f5ac837eafac7c2c25a4fafd5049fde583d Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:14:06 +0100 Subject: [PATCH 065/115] Using manager.isLocked instead of removed checkTouchLocked method for mute property --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 837fca060..45e092da8 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -266,7 +266,7 @@ Object.defineProperty(HTML5AudioSound.prototype, 'mute', { }, set: function (value) { this.currentConfig.mute = value; - if (this.checkTouchLocked('property', 'mute', value)) { + if (this.manager.isLocked(this, 'mute', value)) { return; } this.setMute(); From 94d7fb7d4f80ee7e711d4a28de03f0a915cc52c0 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:14:18 +0100 Subject: [PATCH 066/115] Using manager.isLocked instead of removed checkTouchLocked method for volume property --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 45e092da8..240e66990 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -285,7 +285,7 @@ Object.defineProperty(HTML5AudioSound.prototype, 'volume', { }, set: function (value) { this.currentConfig.volume = value; - if (this.checkTouchLocked('property', 'volume', value)) { + if (this.manager.isLocked(this, 'volume', value)) { return; } this.setVolume(); From 99c9b786c8f54eaa286ed9ff2547ad89299dce86 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:14:33 +0100 Subject: [PATCH 067/115] Using manager.isLocked instead of removed checkTouchLocked method for rate property --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 240e66990..b5049384e 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -304,7 +304,7 @@ Object.defineProperty(HTML5AudioSound.prototype, 'rate', { }, set: function (value) { this.currentConfig.rate = value; - if (this.checkTouchLocked('property', 'rate', value)) { + if (this.manager.isLocked(this, 'rate', value)) { return; } Object.getOwnPropertyDescriptor(BaseSound.prototype, 'rate').set.call(this, value); From 216bde957734e0b7d16cc67a860598c284760957 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:14:43 +0100 Subject: [PATCH 068/115] Using manager.isLocked instead of removed checkTouchLocked method for detune property --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index b5049384e..384b9baa6 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -322,7 +322,7 @@ Object.defineProperty(HTML5AudioSound.prototype, 'detune', { }, set: function (value) { this.currentConfig.detune = value; - if (this.checkTouchLocked('property', 'detune', value)) { + if (this.manager.isLocked(this, 'detune', value)) { return; } Object.getOwnPropertyDescriptor(BaseSound.prototype, 'detune').set.call(this, value); From 25f22533fdbae547f0c89fe09c93290f81192776 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:14:55 +0100 Subject: [PATCH 069/115] Using manager.isLocked instead of removed checkTouchLocked method for seek property --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 384b9baa6..13eddc389 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -348,7 +348,7 @@ Object.defineProperty(HTML5AudioSound.prototype, 'seek', { } }, set: function (value) { - if (this.checkTouchLocked('property', 'seek', value)) { + if (this.manager.isLocked(this, 'seek', value)) { return; } if (this.startTime > 0) { From 252b577ab4aa72ac747bcf719bbc592e280e5d66 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:15:09 +0100 Subject: [PATCH 070/115] Using manager.isLocked instead of removed checkTouchLocked method for loop property --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 13eddc389..80ee4553a 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -380,7 +380,7 @@ Object.defineProperty(HTML5AudioSound.prototype, 'loop', { }, set: function (value) { this.currentConfig.loop = value; - if (this.checkTouchLocked('property', 'loop', value)) { + if (this.manager.isLocked(this, 'loop', value)) { return; } if (this.audio) { From 6be1406b8b6b37e372928dcf80591f036551b60d Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Wed, 17 Jan 2018 19:16:21 +0100 Subject: [PATCH 071/115] Renamed locked action name property to prop --- src/sound/html5/HTML5AudioSoundManager.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index a6ca6eb28..497c661ff 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -107,11 +107,11 @@ var HTML5AudioSoundManager = new Class({ }; this.once('unlocked', function () { _this.lockedActionsQueue.forEach(function (lockedAction) { - if (lockedAction.sound[lockedAction.name].apply) { - lockedAction.sound[lockedAction.name].apply(lockedAction.sound, lockedAction.value || []); + if (lockedAction.sound[lockedAction.prop].apply) { + lockedAction.sound[lockedAction.prop].apply(lockedAction.sound, lockedAction.value || []); } else { - lockedAction.sound[lockedAction.name] = lockedAction.value; + lockedAction.sound[lockedAction.prop] = lockedAction.value; } }); _this.lockedActionsQueue.length = 0; @@ -138,11 +138,11 @@ var HTML5AudioSoundManager = new Class({ this.onBlurPausedSounds.length = 0; this.onBlurPausedSounds = null; }, - isLocked: function (sound, name, value) { + isLocked: function (sound, prop, value) { if (this.locked) { this.lockedActionsQueue.push({ sound: sound, - name: name, + prop: prop, value: value }); return true; From b61a4dec6667cddb2aa491a84c9513ad27c1c46e Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:04:41 +0100 Subject: [PATCH 072/115] Passing sound manager locked property value instead of touchLocked to HTML5AudioFile constructor --- src/loader/filetypes/AudioFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loader/filetypes/AudioFile.js b/src/loader/filetypes/AudioFile.js index 4f48b09a3..449fefadf 100644 --- a/src/loader/filetypes/AudioFile.js +++ b/src/loader/filetypes/AudioFile.js @@ -83,7 +83,7 @@ AudioFile.create = function (loader, key, urls, config, xhrSettings) return new AudioFile(key, url, loader.path, xhrSettings, game.sound.context); } - return new HTML5AudioFile(key, url, loader.path, config, game.sound.touchLocked); + return new HTML5AudioFile(key, url, loader.path, config, game.sound.locked); }; // this.load.audio('sound', 'assets/audio/booom.ogg', config, xhrSettings); From 345f112ff8b68a3d93d61b51749a81bf85579ecd Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:05:20 +0100 Subject: [PATCH 073/115] Renamed touchLocked to locked --- src/loader/filetypes/HTML5AudioFile.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/loader/filetypes/HTML5AudioFile.js b/src/loader/filetypes/HTML5AudioFile.js index 5cbe867bb..12c45cea4 100644 --- a/src/loader/filetypes/HTML5AudioFile.js +++ b/src/loader/filetypes/HTML5AudioFile.js @@ -11,9 +11,9 @@ var HTML5AudioFile = new Class({ initialize: - function HTML5AudioFile (key, url, path, config, touchLocked) + function HTML5AudioFile (key, url, path, config, locked) { - this.touchLocked = touchLocked; + this.locked = locked; var fileConfig = { type: 'audio', @@ -77,7 +77,7 @@ var HTML5AudioFile = new Class({ audio.dataset.name = this.key + ('0' + i).slice(-2); // Useful for debugging audio.dataset.used = 'false'; - if (!this.touchLocked) + if (!this.locked) { audio.preload = 'auto'; audio.oncanplaythrough = this.onProgress.bind(this); @@ -92,13 +92,13 @@ var HTML5AudioFile = new Class({ audio = this.data[i]; audio.src = GetURL(this, baseURL || ''); - if (!this.touchLocked) + if (!this.locked) { audio.load(); } } - if (this.touchLocked) + if (this.locked) { setTimeout(function () { From 58d6ab9a560ede651f7fec3f0ee34712a262220e Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:06:29 +0100 Subject: [PATCH 074/115] Emitting ready event if sound manager is not locked --- src/sound/BaseSoundManager.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index ab36167fd..30e71c2d3 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -119,6 +119,9 @@ var BaseSoundManager = new Class({ if (this.locked) { this.unlock(); } + else { + this.emit('ready', this); + } }, /** * Adds a new sound into the sound manager. From c296ef2eb398434b0e1b444b466bf97f9e181e53 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:07:35 +0100 Subject: [PATCH 075/115] Emitting ready event when sound manager gets unlocked --- src/sound/BaseSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 30e71c2d3..0694f2946 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -315,6 +315,7 @@ var BaseSoundManager = new Class({ this.unlocked = false; this.locked = false; this.emit('unlocked', this); + this.emit('ready', this); } for (var i = this.sounds.length - 1; i >= 0; i--) { if (this.sounds[i].pendingRemove) { From 9400c7ea93bc7380cd4977869db6e1c0b766c8b2 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:08:33 +0100 Subject: [PATCH 076/115] Setting correct duration property value for all sounds when audio gets unlocked --- src/sound/html5/HTML5AudioSoundManager.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 497c661ff..bea063786 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -106,6 +106,9 @@ var HTML5AudioSoundManager = new Class({ }); }; this.once('unlocked', function () { + _this.forEachActiveSound(function (sound) { + sound.duration = sound.tags[0].duration; + }); _this.lockedActionsQueue.forEach(function (lockedAction) { if (lockedAction.sound[lockedAction.prop].apply) { lockedAction.sound[lockedAction.prop].apply(lockedAction.sound, lockedAction.value || []); From 718dce88b8352611cf5422dd8fa1ad48111da7f6 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:08:49 +0100 Subject: [PATCH 077/115] Setting correct totalDuration property value for all sounds when audio gets unlocked --- src/sound/html5/HTML5AudioSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index bea063786..b4478e8d4 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -108,6 +108,7 @@ var HTML5AudioSoundManager = new Class({ this.once('unlocked', function () { _this.forEachActiveSound(function (sound) { sound.duration = sound.tags[0].duration; + sound.totalDuration = sound.tags[0].duration; }); _this.lockedActionsQueue.forEach(function (lockedAction) { if (lockedAction.sound[lockedAction.prop].apply) { From 01c246ac0b582c2474e7252e64d6d2b23b36be6c Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:10:03 +0100 Subject: [PATCH 078/115] Added variable and method for keeping track of touch move events --- src/sound/html5/HTML5AudioSoundManager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index b4478e8d4..359c8ac23 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -87,6 +87,10 @@ var HTML5AudioSoundManager = new Class({ }, unlock: function () { var _this = this; + var moved = false; + var detectMove = function () { + moved = true; + }; var unlock = function () { document.body.removeEventListener('touchend', unlock); var allTags = []; From b036eecd9f7f56439c588d1abed4312e32f07fbb Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:10:51 +0100 Subject: [PATCH 079/115] Added detectMove method as touchmove event listener --- src/sound/html5/HTML5AudioSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 359c8ac23..44298e6a2 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -125,6 +125,7 @@ var HTML5AudioSoundManager = new Class({ _this.lockedActionsQueue.length = 0; _this.lockedActionsQueue = null; }); + document.body.addEventListener('touchmove', detectMove, false); document.body.addEventListener('touchend', unlock, false); }, onBlur: function () { From 336f5b9028145862f961f56d571bf8e2547bf120 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:11:49 +0100 Subject: [PATCH 080/115] Skipping unlocking if touchmove event occurred before touchend event --- src/sound/html5/HTML5AudioSoundManager.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 44298e6a2..2d909d617 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -92,6 +92,10 @@ var HTML5AudioSoundManager = new Class({ moved = true; }; var unlock = function () { + if (moved) { + moved = false; + return; + } document.body.removeEventListener('touchend', unlock); var allTags = []; _this.game.cache.audio.entries.each(function (key, tags) { From c1cb3c3ab25e6e3d01cd49cc978c15527f97b86d Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:12:32 +0100 Subject: [PATCH 081/115] Removing touchmove event listener on successful unlock --- src/sound/html5/HTML5AudioSoundManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sound/html5/HTML5AudioSoundManager.js b/src/sound/html5/HTML5AudioSoundManager.js index 2d909d617..c46f4d458 100644 --- a/src/sound/html5/HTML5AudioSoundManager.js +++ b/src/sound/html5/HTML5AudioSoundManager.js @@ -96,6 +96,7 @@ var HTML5AudioSoundManager = new Class({ moved = false; return; } + document.body.removeEventListener('touchmove', detectMove); document.body.removeEventListener('touchend', unlock); var allTags = []; _this.game.cache.audio.entries.each(function (key, tags) { From ef98de7258cf5e589cc612afaeace70a8672095f Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:13:29 +0100 Subject: [PATCH 082/115] Added playCatchPromise method to handle possible exceptions thrown form audio tag play method --- src/sound/html5/HTML5AudioSound.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 80ee4553a..24c2bf3f3 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -169,6 +169,12 @@ var HTML5AudioSound = new Class({ } return true; }, + playCatchPromise: function () { + var playPromise = this.audio.play(); + if (playPromise) { + playPromise.catch(function (reason) { }); + } + }, stopAndReleaseAudioTag: function () { this.audio.pause(); this.audio.dataset.used = 'false'; From 3a7d06b48a563048f966cd31f2895e3035233105 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:13:57 +0100 Subject: [PATCH 083/115] Using playCatchPromise when starting sound playback --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 24c2bf3f3..7d1e02de4 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -122,7 +122,7 @@ var HTML5AudioSound = new Class({ if (delay === 0) { this.startTime = 0; if (this.audio.paused) { - this.audio.play(); + this.playCatchPromise(); } } else { From ca614166b1b3885bb41df3d322418fa0dfe03abe Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:14:14 +0100 Subject: [PATCH 084/115] Using playCatchPromise for delayed sound playback --- src/sound/html5/HTML5AudioSound.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 7d1e02de4..a1e8b22d8 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -206,7 +206,7 @@ var HTML5AudioSound = new Class({ this.audio.currentTime += Math.max(0, time - this.startTime) / 1000; this.startTime = 0; this.previousTime = this.audio.currentTime; - this.audio.play(); + this.playCatchPromise(); } return; } From 8968044d8f231892d19af56def397e6ebfe0c28c Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Thu, 18 Jan 2018 14:15:15 +0100 Subject: [PATCH 085/115] Removed ready event --- src/sound/BaseSoundManager.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sound/BaseSoundManager.js b/src/sound/BaseSoundManager.js index 0694f2946..ab36167fd 100644 --- a/src/sound/BaseSoundManager.js +++ b/src/sound/BaseSoundManager.js @@ -119,9 +119,6 @@ var BaseSoundManager = new Class({ if (this.locked) { this.unlock(); } - else { - this.emit('ready', this); - } }, /** * Adds a new sound into the sound manager. @@ -315,7 +312,6 @@ var BaseSoundManager = new Class({ this.unlocked = false; this.locked = false; this.emit('unlocked', this); - this.emit('ready', this); } for (var i = this.sounds.length - 1; i >= 0; i--) { if (this.sounds[i].pendingRemove) { From 4bb855708181e60d41605dbfe44b289d62e5eb38 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Fri, 19 Jan 2018 12:06:11 +0100 Subject: [PATCH 086/115] Updated reference to the game object --- src/loader/filetypes/AudioFile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/loader/filetypes/AudioFile.js b/src/loader/filetypes/AudioFile.js index 449fefadf..5bfc1c284 100644 --- a/src/loader/filetypes/AudioFile.js +++ b/src/loader/filetypes/AudioFile.js @@ -60,7 +60,7 @@ var AudioFile = new Class({ AudioFile.create = function (loader, key, urls, config, xhrSettings) { - var game = loader.scene.game; + var game = loader.scene.sys.game; var audioConfig = game.config.audio; var deviceAudio = game.device.Audio; From fb96aeccd6d7d6ece25682b774911ddc1c56fed4 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Fri, 19 Jan 2018 12:06:41 +0100 Subject: [PATCH 087/115] Removed game reference --- src/boot/DebugHeader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/DebugHeader.js b/src/boot/DebugHeader.js index eb7a45ceb..a4fa4413e 100644 --- a/src/boot/DebugHeader.js +++ b/src/boot/DebugHeader.js @@ -20,7 +20,7 @@ var DebugHeader = function (game) var renderType = (config.renderType === CONST.CANVAS) ? 'Canvas' : 'WebGL'; - var audioConfig = game.config.audio; + var audioConfig = config.audio; var deviceAudio = game.device.Audio; var audioType; From ff8c039cf713158f4c84ff5a3503d974c10162db Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Fri, 19 Jan 2018 12:17:34 +0100 Subject: [PATCH 088/115] Inverted condition to prevent nesting --- src/sound/html5/HTML5AudioSound.js | 63 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index a1e8b22d8..b8c2df149 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -135,38 +135,39 @@ var HTML5AudioSound = new Class({ return true; }, pickAudioTag: function () { - if (!this.audio) { - for (var i = 0; i < this.tags.length; i++) { - var audio = this.tags[i]; - if (audio.dataset.used === 'false') { - audio.dataset.used = 'true'; - this.audio = audio; - return true; - } - } - if (!this.manager.override) { - return false; - } - var otherSounds_1 = []; - this.manager.forEachActiveSound(function (sound) { - if (sound.key === this.key && sound.audio) { - otherSounds_1.push(sound); - } - }, this); - otherSounds_1.sort(function (a1, a2) { - if (a1.loop === a2.loop) { - // sort by progress - return (a2.seek / a2.duration) - (a1.seek / a1.duration); - } - return a1.loop ? 1 : -1; - }); - var selectedSound = otherSounds_1[0]; - this.audio = selectedSound.audio; - selectedSound.reset(); - selectedSound.audio = null; - selectedSound.startTime = 0; - selectedSound.previousTime = 0; + if (this.audio) { + return true; } + for (var i = 0; i < this.tags.length; i++) { + var audio = this.tags[i]; + if (audio.dataset.used === 'false') { + audio.dataset.used = 'true'; + this.audio = audio; + return true; + } + } + if (!this.manager.override) { + return false; + } + var otherSounds = []; + this.manager.forEachActiveSound(function (sound) { + if (sound.key === this.key && sound.audio) { + otherSounds.push(sound); + } + }, this); + otherSounds.sort(function (a1, a2) { + if (a1.loop === a2.loop) { + // sort by progress + return (a2.seek / a2.duration) - (a1.seek / a1.duration); + } + return a1.loop ? 1 : -1; + }); + var selectedSound = otherSounds[0]; + this.audio = selectedSound.audio; + selectedSound.reset(); + selectedSound.audio = null; + selectedSound.startTime = 0; + selectedSound.previousTime = 0; return true; }, playCatchPromise: function () { From f7b0dcf56a13bff48cf28847cf1390291874e47e Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Fri, 19 Jan 2018 12:19:02 +0100 Subject: [PATCH 089/115] Inverted condition to prevent nesting --- src/sound/html5/HTML5AudioSound.js | 71 +++++++++++++++--------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index b8c2df149..4750430ed 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -200,42 +200,43 @@ var HTML5AudioSound = new Class({ this.pickAndPlayAudioTag(); }, update: function (time, delta) { - if (this.isPlaying) { - // handling delayed playback - if (this.startTime > 0) { - if (this.startTime < time - this.manager.audioPlayDelay) { - this.audio.currentTime += Math.max(0, time - this.startTime) / 1000; - this.startTime = 0; - this.previousTime = this.audio.currentTime; - this.playCatchPromise(); - } - return; - } - // handle looping and ending - var startTime = this.currentMarker ? this.currentMarker.start : 0; - var endTime = startTime + this.duration; - var currentTime = this.audio.currentTime; - if (this.currentConfig.loop) { - if (currentTime >= endTime - this.manager.loopEndOffset) { - this.audio.currentTime = startTime + Math.max(0, currentTime - endTime); - currentTime = this.audio.currentTime; - } - else if (currentTime < startTime) { - this.audio.currentTime += startTime; - currentTime = this.audio.currentTime; - } - if (currentTime < this.previousTime) { - this.emit('looped', this); - } - } - else if (currentTime >= endTime) { - this.reset(); - this.stopAndReleaseAudioTag(); - this.emit('ended', this); - return; - } - this.previousTime = currentTime; + if (!this.isPlaying) { + return; } + // handling delayed playback + if (this.startTime > 0) { + if (this.startTime < time - this.manager.audioPlayDelay) { + this.audio.currentTime += Math.max(0, time - this.startTime) / 1000; + this.startTime = 0; + this.previousTime = this.audio.currentTime; + this.playCatchPromise(); + } + return; + } + // handle looping and ending + var startTime = this.currentMarker ? this.currentMarker.start : 0; + var endTime = startTime + this.duration; + var currentTime = this.audio.currentTime; + if (this.currentConfig.loop) { + if (currentTime >= endTime - this.manager.loopEndOffset) { + this.audio.currentTime = startTime + Math.max(0, currentTime - endTime); + currentTime = this.audio.currentTime; + } + else if (currentTime < startTime) { + this.audio.currentTime += startTime; + currentTime = this.audio.currentTime; + } + if (currentTime < this.previousTime) { + this.emit('looped', this); + } + } + else if (currentTime >= endTime) { + this.reset(); + this.stopAndReleaseAudioTag(); + this.emit('ended', this); + return; + } + this.previousTime = currentTime; }, destroy: function () { BaseSound.prototype.destroy.call(this); From a6365c53391c69ac233819da21e35f061ece995c Mon Sep 17 00:00:00 2001 From: Michael Hadley Date: Fri, 19 Jan 2018 06:56:52 -0600 Subject: [PATCH 090/115] Removing es6 'let' from AP vs tilemap --- src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js index 0c1f6d04d..d0db7d9de 100644 --- a/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js +++ b/src/physics/arcade/inc/CollideSpriteVsTilemapLayer.js @@ -23,14 +23,14 @@ var CollideSpriteVsTilemapLayer = function (sprite, tilemapLayer, collideCallbac if (layerData.tileWidth > layerData.baseTileWidth) { // The x origin of a tile is the left side, so x and width need to be adjusted. - let xDiff = (layerData.tileWidth - layerData.baseTileWidth) * tilemapLayer.scaleX; + var xDiff = (layerData.tileWidth - layerData.baseTileWidth) * tilemapLayer.scaleX; x -= xDiff; w += xDiff; } if (layerData.tileHeight > layerData.baseTileHeight) { // The y origin of a tile is the bottom side, so just the height needs to be adjusted. - let yDiff = (layerData.tileHeight - layerData.baseTileHeight) * tilemapLayer.scaleY; + var yDiff = (layerData.tileHeight - layerData.baseTileHeight) * tilemapLayer.scaleY; h += yDiff; } From df7bc2e841797bdad5a7006a0a8e317b1cad5e7c Mon Sep 17 00:00:00 2001 From: Antriel Date: Fri, 19 Jan 2018 14:20:45 +0100 Subject: [PATCH 091/115] Added missing require for Point. --- src/geom/point/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/geom/point/index.js b/src/geom/point/index.js index c1c59199b..84e10bb50 100644 --- a/src/geom/point/index.js +++ b/src/geom/point/index.js @@ -14,6 +14,7 @@ Point.Floor = require('./Floor'); Point.GetCentroid = require('./GetCentroid'); Point.GetMagnitude = require('./GetMagnitude'); Point.GetMagnitudeSq = require('./GetMagnitudeSq'); +Point.GetRectangleFromPoints = require('./GetRectangleFromPoints'); Point.Interpolate = require('./Interpolate'); Point.Invert = require('./Invert'); Point.Multiply = require('./Multiply'); From fd4cae12fcf39c74adc58a8708438c89051ba122 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 13:28:30 +0000 Subject: [PATCH 092/115] Removed un-used file. --- src/plugins/TestPlugin.js | 42 --------------------------------------- 1 file changed, 42 deletions(-) delete mode 100644 src/plugins/TestPlugin.js diff --git a/src/plugins/TestPlugin.js b/src/plugins/TestPlugin.js deleted file mode 100644 index 2f05c870b..000000000 --- a/src/plugins/TestPlugin.js +++ /dev/null @@ -1,42 +0,0 @@ -var Class = require('../utils/Class'); -var PluginManager = require('../plugins/PluginManager'); - -var TestPlugin = new Class({ - - initialize: - - function TestPlugin (scene) - { - this.scene = scene; - - this.systems = scene.sys; - - this.mapping = 'test'; - - console.log('TestPlugin is alive'); - - if (!scene.sys.settings.isBooted) - { - scene.sys.events.once('boot', this.boot, this); - } - }, - - boot: function () - { - console.log('TestPlugin has booted'); - - this.scene[this.mapping] = this; - }, - - fire: function (img) - { - console.log('Hello!'); - - this.systems.add.image(400, 300, img); - } - -}); - -PluginManager.register('test', TestPlugin); - -module.exports = TestPlugin; From 676c5be1da51530415a9a50c4e615683cdcd4c1b Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 13:28:42 +0000 Subject: [PATCH 093/115] Added global FileTypes manager. --- src/loader/FileTypesManager.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/loader/FileTypesManager.js diff --git a/src/loader/FileTypesManager.js b/src/loader/FileTypesManager.js new file mode 100644 index 000000000..1c2a82469 --- /dev/null +++ b/src/loader/FileTypesManager.js @@ -0,0 +1,27 @@ +var types = {}; + +var FileTypesManager = { + + install: function (loader) + { + for (var key in types) + { + loader[key] = types[key]; + } + }, + + register: function (key, factoryFunction) + { + types[key] = factoryFunction; + + // console.log('FileTypesManager.register', key); + }, + + destroy: function () + { + types = {}; + } + +}; + +module.exports = FileTypesManager; From db515d8724c679b3063679d323433bb34e447c40 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 13:29:15 +0000 Subject: [PATCH 094/115] All FileTypes now register themselves with the FileTypesManager, allowing devs to specify which loaders are included in their builds. --- src/loader/Loader.js | 35 ++++++++------------ src/loader/filetypes/AnimationJSONFile.js | 19 ++++++++--- src/loader/filetypes/AtlasJSONFile.js | 14 ++++++++ src/loader/filetypes/AudioFile.js | 35 +++++++++++++++----- src/loader/filetypes/BinaryFile.js | 17 +++++++--- src/loader/filetypes/BitmapFontFile.js | 18 +++++++++++ src/loader/filetypes/GLSLFile.js | 17 +++++++--- src/loader/filetypes/HTMLFile.js | 17 +++++++--- src/loader/filetypes/ImageFile.js | 19 +++++++---- src/loader/filetypes/JSONFile.js | 17 +++++++--- src/loader/filetypes/PluginFile.js | 17 +++++++--- src/loader/filetypes/SVGFile.js | 17 +++++++--- src/loader/filetypes/ScriptFile.js | 17 +++++++--- src/loader/filetypes/SpriteSheet.js | 18 ++++++++--- src/loader/filetypes/TextFile.js | 17 +++++++--- src/loader/filetypes/TilemapCSVFile.js | 20 ++++++++---- src/loader/filetypes/TilemapJSONFile.js | 39 ++++++++++++++++++++--- src/loader/filetypes/UnityAtlasFile.js | 19 +++++++++++ src/loader/filetypes/WavefrontFile.js | 17 +++++++--- src/loader/filetypes/XMLFile.js | 17 +++++++--- src/loader/index.js | 25 ++++++++++++++- 21 files changed, 323 insertions(+), 108 deletions(-) diff --git a/src/loader/Loader.js b/src/loader/Loader.js index 409c42714..cb2f95300 100644 --- a/src/loader/Loader.js +++ b/src/loader/Loader.js @@ -1,30 +1,9 @@ var BaseLoader = require('./BaseLoader'); var Class = require('../utils/Class'); var CONST = require('./const'); +var FileTypesManager = require('./FileTypesManager'); var NumberArray = require('../utils/array/NumberArray'); var PluginManager = require('../plugins/PluginManager'); -var TILEMAP_FORMATS = require('../gameobjects/tilemap/Formats'); - -// TODO - Injection mapped -var AnimationJSONFile = require('./filetypes/AnimationJSONFile'); -var AtlasJSONFile = require('./filetypes/AtlasJSONFile'); -var AudioFile = require('./filetypes/AudioFile'); -var BinaryFile = require('./filetypes/BinaryFile'); -var BitmapFontFile = require('./filetypes/BitmapFontFile'); -var GLSLFile = require('./filetypes/GLSLFile'); -var HTMLFile = require('./filetypes/HTMLFile'); -var ImageFile = require('./filetypes/ImageFile'); -var JSONFile = require('./filetypes/JSONFile'); -var PluginFile = require('./filetypes/PluginFile'); -var ScriptFile = require('./filetypes/ScriptFile'); -var SpriteSheet = require('./filetypes/SpriteSheet'); -var SVGFile = require('./filetypes/SVGFile'); -var TextFile = require('./filetypes/TextFile'); -var TilemapCSVFile = require('./filetypes/TilemapCSVFile'); -var TilemapJSONFile = require('./filetypes/TilemapJSONFile'); -var UnityAtlasFile = require('./filetypes/UnityAtlasFile'); -var WavefrontFile = require('./filetypes/WavefrontFile'); -var XMLFile = require('./filetypes/XMLFile'); var Loader = new Class({ @@ -44,6 +23,9 @@ var Loader = new Class({ } this._multilist = {}; + + // Inject the available filetypes into the Loader + FileTypesManager.install(this); }, boot: function () @@ -56,6 +38,7 @@ var Loader = new Class({ // key can be either a string, an object or an array of objects + /* image: function (key, url, xhrSettings) { return ImageFile.create(this, key, url, xhrSettings); @@ -86,6 +69,7 @@ var Loader = new Class({ return XMLFile.create(this, key, url, xhrSettings); }, + /* binary: function (key, url, xhrSettings) { return BinaryFile.create(this, key, url, xhrSettings); @@ -121,8 +105,10 @@ var Loader = new Class({ { return SpriteSheet.create(this, key, url, config, xhrSettings); }, + */ // config can include: instances + /* audio: function (key, urls, config, xhrSettings) { var audioFile = AudioFile.create(this, key, urls, config, xhrSettings); @@ -134,7 +120,9 @@ var Loader = new Class({ return this; }, + */ + /* tilemapCSV: function (key, url, xhrSettings) { return TilemapCSVFile.create(this, key, url, TILEMAP_FORMATS.CSV, xhrSettings); @@ -149,6 +137,7 @@ var Loader = new Class({ { return TilemapJSONFile.create(this, key, url, TILEMAP_FORMATS.WELTMEISTER, xhrSettings); }, + */ // --------------------------------------------------- // Multi-File Loaders @@ -192,6 +181,7 @@ var Loader = new Class({ return this; }, + /* unityAtlas: function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) { // Returns an object with two properties: 'texture' and 'data' @@ -224,6 +214,7 @@ var Loader = new Class({ return this; }, + */ multiatlas: function (key, textureURLs, atlasURLs, textureXhrSettings, atlasXhrSettings) { diff --git a/src/loader/filetypes/AnimationJSONFile.js b/src/loader/filetypes/AnimationJSONFile.js index 5d3543daf..dfbb30ced 100644 --- a/src/loader/filetypes/AnimationJSONFile.js +++ b/src/loader/filetypes/AnimationJSONFile.js @@ -1,5 +1,8 @@ +var FileTypesManager = require('../FileTypesManager'); var JSONFile = require('./JSONFile.js'); +// Phaser.Loader.FileTypes.AnimationJSONFile + var AnimationJSONFile = function (key, url, path, xhrSettings) { var json = new JSONFile(key, url, path, xhrSettings); @@ -10,23 +13,29 @@ var AnimationJSONFile = function (key, url, path, xhrSettings) return json; }; -AnimationJSONFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('animation', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new AnimationJSONFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new AnimationJSONFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new AnimationJSONFile(key, url, loader.path, xhrSettings)); + this.addFile(new AnimationJSONFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = AnimationJSONFile; diff --git a/src/loader/filetypes/AtlasJSONFile.js b/src/loader/filetypes/AtlasJSONFile.js index 0ceb639c8..2f4c65c79 100644 --- a/src/loader/filetypes/AtlasJSONFile.js +++ b/src/loader/filetypes/AtlasJSONFile.js @@ -1,6 +1,9 @@ +var FileTypesManager = require('../FileTypesManager'); var ImageFile = require('./ImageFile.js'); var JSONFile = require('./JSONFile.js'); +// Phaser.Loader.FileTypes.AtlasJSONFile + var AtlasJSONFile = function (key, textureURL, atlasURL, path, textureXhrSettings, atlasXhrSettings) { var image = new ImageFile(key, textureURL, path, textureXhrSettings); @@ -17,4 +20,15 @@ var AtlasJSONFile = function (key, textureURL, atlasURL, path, textureXhrSetting return { texture: image, data: data }; }; +FileTypesManager.register('atlas', function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) +{ + // Returns an object with two properties: 'texture' and 'data' + var files = new AtlasJSONFile(key, textureURL, atlasURL, this.path, textureXhrSettings, atlasXhrSettings); + + this.addFile(files.texture); + this.addFile(files.data); + + return this; +}); + module.exports = AtlasJSONFile; diff --git a/src/loader/filetypes/AudioFile.js b/src/loader/filetypes/AudioFile.js index 4e1dd28bd..738645e2d 100644 --- a/src/loader/filetypes/AudioFile.js +++ b/src/loader/filetypes/AudioFile.js @@ -1,5 +1,6 @@ var Class = require('../../utils/Class'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); var CONST = require('../../const'); var HTML5AudioFile = require('./HTML5AudioFile'); @@ -58,16 +59,22 @@ var AudioFile = new Class({ }); -AudioFile.create = function (loader, key, urls, config, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('audio', function (key, urls, config, xhrSettings) { - var game = loader.scene.game; + var game = this.systems.game; var audioConfig = game.config.audio; var deviceAudio = game.device.Audio; if ((audioConfig && audioConfig.noAudio) || (!deviceAudio.webAudio && !deviceAudio.audioData)) { console.info('Skipping loading audio \'' + key + '\' since sounds are disabled.'); - return null; + return this; } var url = AudioFile.findAudioURL(game, urls); @@ -75,16 +82,27 @@ AudioFile.create = function (loader, key, urls, config, xhrSettings) if (!url) { console.warn('No supported url provided for audio \'' + key + '\'!'); - return null; + return this; } - if(deviceAudio.webAudio && !(audioConfig && audioConfig.disableWebAudio)) + var audioFile; + + if (deviceAudio.webAudio && !(audioConfig && audioConfig.disableWebAudio)) { - return new AudioFile(key, url, loader.path, xhrSettings, game.sound.context); + audioFile = new AudioFile(key, url, this.path, xhrSettings, game.sound.context); + } + else + { + audioFile = new HTML5AudioFile(key, url, this.path, config); } - return new HTML5AudioFile(key, url, loader.path, config); -}; + if (audioFile) + { + this.addFile(audioFile); + } + + return this; +}); // this.load.audio('sound', 'assets/audio/booom.ogg', config, xhrSettings); // @@ -129,6 +147,7 @@ AudioFile.create = function (loader, key, urls, config, xhrSettings) // } // ], // config, xhrSettings); + AudioFile.findAudioURL = function (game, urls) { if (urls.constructor !== Array) diff --git a/src/loader/filetypes/BinaryFile.js b/src/loader/filetypes/BinaryFile.js index 00487f4e7..ef067872e 100644 --- a/src/loader/filetypes/BinaryFile.js +++ b/src/loader/filetypes/BinaryFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); // Phaser.Loader.FileTypes.BinaryFile @@ -41,23 +42,29 @@ var BinaryFile = new Class({ }); -BinaryFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('binary', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new BinaryFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new BinaryFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new BinaryFile(key, url, loader.path, xhrSettings)); + this.addFile(new BinaryFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = BinaryFile; diff --git a/src/loader/filetypes/BitmapFontFile.js b/src/loader/filetypes/BitmapFontFile.js index ced6412a8..aa28509a7 100644 --- a/src/loader/filetypes/BitmapFontFile.js +++ b/src/loader/filetypes/BitmapFontFile.js @@ -1,3 +1,4 @@ +var FileTypesManager = require('../FileTypesManager'); var ImageFile = require('./ImageFile.js'); var XMLFile = require('./XMLFile.js'); @@ -17,4 +18,21 @@ var BitmapFontFile = function (key, textureURL, xmlURL, path, textureXhrSettings return { texture: image, data: data }; }; +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('bitmapFont', function (key, textureURL, xmlURL, textureXhrSettings, xmlXhrSettings) +{ + // Returns an object with two properties: 'texture' and 'data' + var files = new BitmapFontFile(key, textureURL, xmlURL, this.path, textureXhrSettings, xmlXhrSettings); + + this.addFile(files.texture); + this.addFile(files.data); + + return this; +}); + module.exports = BitmapFontFile; diff --git a/src/loader/filetypes/GLSLFile.js b/src/loader/filetypes/GLSLFile.js index 80bf6f9e9..9d05938aa 100644 --- a/src/loader/filetypes/GLSLFile.js +++ b/src/loader/filetypes/GLSLFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); // Phaser.Loader.FileTypes.GLSLFile @@ -41,23 +42,29 @@ var GLSLFile = new Class({ }); -GLSLFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('glsl', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new GLSLFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new GLSLFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new GLSLFile(key, url, loader.path, xhrSettings)); + this.addFile(new GLSLFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = GLSLFile; diff --git a/src/loader/filetypes/HTMLFile.js b/src/loader/filetypes/HTMLFile.js index db1f53912..de944454e 100644 --- a/src/loader/filetypes/HTMLFile.js +++ b/src/loader/filetypes/HTMLFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); // Phaser.Loader.FileTypes.HTMLFile @@ -95,23 +96,29 @@ var HTMLFile = new Class({ }); -HTMLFile.create = function (loader, key, url, width, height, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('html', function (key, url, width, height, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new HTMLFile(key[i], url, width, height, loader.path, xhrSettings)); + this.addFile(new HTMLFile(key[i], url, width, height, this.path, xhrSettings)); } } else { - loader.addFile(new HTMLFile(key, url, width, height, loader.path, xhrSettings)); + this.addFile(new HTMLFile(key, url, width, height, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = HTMLFile; diff --git a/src/loader/filetypes/ImageFile.js b/src/loader/filetypes/ImageFile.js index ffed0a1fc..323d74363 100644 --- a/src/loader/filetypes/ImageFile.js +++ b/src/loader/filetypes/ImageFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); // Phaser.Loader.FileTypes.ImageFile @@ -26,6 +27,7 @@ var ImageFile = new Class({ // }); // this.load.image({ key: 'bunny' }); // this.load.image({ key: 'bunny', extension: 'jpg' }); + function ImageFile (key, url, path, xhrSettings, config) { var fileKey = (typeof key === 'string') ? key : GetFastValue(key, 'key', ''); @@ -73,28 +75,33 @@ var ImageFile = new Class({ }; File.createObjectURL(this.data, this.xhrLoader.response, 'image/png'); - } }); -ImageFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('image', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new ImageFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new ImageFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new ImageFile(key, url, loader.path, xhrSettings)); + this.addFile(new ImageFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = ImageFile; diff --git a/src/loader/filetypes/JSONFile.js b/src/loader/filetypes/JSONFile.js index 1ba0c7714..9d8bb0905 100644 --- a/src/loader/filetypes/JSONFile.js +++ b/src/loader/filetypes/JSONFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); // Phaser.Loader.FileTypes.JSONFile @@ -41,23 +42,29 @@ var JSONFile = new Class({ }); -JSONFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('json', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new JSONFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new JSONFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new JSONFile(key, url, loader.path, xhrSettings)); + this.addFile(new JSONFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = JSONFile; diff --git a/src/loader/filetypes/PluginFile.js b/src/loader/filetypes/PluginFile.js index 915dbef48..d4decb0bb 100644 --- a/src/loader/filetypes/PluginFile.js +++ b/src/loader/filetypes/PluginFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); var PluginManager = require('../../plugins/PluginManager'); @@ -51,23 +52,29 @@ var PluginFile = new Class({ }); -PluginFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('plugin', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new PluginFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new PluginFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new PluginFile(key, url, loader.path, xhrSettings)); + this.addFile(new PluginFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = PluginFile; diff --git a/src/loader/filetypes/SVGFile.js b/src/loader/filetypes/SVGFile.js index 79881c82d..721988770 100644 --- a/src/loader/filetypes/SVGFile.js +++ b/src/loader/filetypes/SVGFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); // Phaser.Loader.FileTypes.SVGFile @@ -90,23 +91,29 @@ var SVGFile = new Class({ }); -SVGFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('svg', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new SVGFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new SVGFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new SVGFile(key, url, loader.path, xhrSettings)); + this.addFile(new SVGFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = SVGFile; diff --git a/src/loader/filetypes/ScriptFile.js b/src/loader/filetypes/ScriptFile.js index 4c6d4f275..56040f6ca 100644 --- a/src/loader/filetypes/ScriptFile.js +++ b/src/loader/filetypes/ScriptFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); // Phaser.Loader.FileTypes.ScriptFile @@ -47,23 +48,29 @@ var ScriptFile = new Class({ }); -ScriptFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('script', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new ScriptFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new ScriptFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new ScriptFile(key, url, loader.path, xhrSettings)); + this.addFile(new ScriptFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = ScriptFile; diff --git a/src/loader/filetypes/SpriteSheet.js b/src/loader/filetypes/SpriteSheet.js index a3ab19dba..1cca08f49 100644 --- a/src/loader/filetypes/SpriteSheet.js +++ b/src/loader/filetypes/SpriteSheet.js @@ -1,3 +1,4 @@ +var FileTypesManager = require('../FileTypesManager'); var ImageFile = require('./ImageFile.js'); // config can include: frameWidth, frameHeight, startFrame, endFrame, margin, spacing @@ -12,23 +13,30 @@ var SpriteSheet = function (key, url, config, path, xhrSettings) return image; }; -SpriteSheet.create = function (loader, key, url, config, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +// config can include: frameWidth, frameHeight, startFrame, endFrame, margin, spacing +FileTypesManager.register('spritesheet', function (key, url, config, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new SpriteSheet(key[i], url, null, loader.path, xhrSettings)); + this.addFile(new SpriteSheet(key[i], url, null, this.path, xhrSettings)); } } else { - loader.addFile(new SpriteSheet(key, url, config, loader.path, xhrSettings)); + this.addFile(new SpriteSheet(key, url, config, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = SpriteSheet; diff --git a/src/loader/filetypes/TextFile.js b/src/loader/filetypes/TextFile.js index 4431c2ef0..7f5ffd44b 100644 --- a/src/loader/filetypes/TextFile.js +++ b/src/loader/filetypes/TextFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); // Phaser.Loader.FileTypes.TextFile @@ -38,23 +39,29 @@ var TextFile = new Class({ }); -TextFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('text', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new TextFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new TextFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new TextFile(key, url, loader.path, xhrSettings)); + this.addFile(new TextFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = TextFile; diff --git a/src/loader/filetypes/TilemapCSVFile.js b/src/loader/filetypes/TilemapCSVFile.js index 5d72d6615..9a20c908b 100644 --- a/src/loader/filetypes/TilemapCSVFile.js +++ b/src/loader/filetypes/TilemapCSVFile.js @@ -1,6 +1,8 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); +var TILEMAP_FORMATS = require('../../gameobjects/tilemap/Formats'); // Phaser.Loader.FileTypes.TilemapCSVFile @@ -10,7 +12,7 @@ var TilemapCSVFile = new Class({ initialize: - function TextFile (key, url, path, format, xhrSettings) + function TilemapCSVFile (key, url, path, format, xhrSettings) { var fileConfig = { type: 'tilemapCSV', @@ -40,23 +42,29 @@ var TilemapCSVFile = new Class({ }); -TilemapCSVFile.create = function (loader, key, url, format, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('tilemapCSV', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new TilemapCSVFile(key[i], url, loader.path, format, xhrSettings)); + this.addFile(new TilemapCSVFile(key[i], url, this.path, TILEMAP_FORMATS.CSV, xhrSettings)); } } else { - loader.addFile(new TilemapCSVFile(key, url, loader.path, format, xhrSettings)); + this.addFile(new TilemapCSVFile(key, url, this.path, TILEMAP_FORMATS.CSV, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = TilemapCSVFile; diff --git a/src/loader/filetypes/TilemapJSONFile.js b/src/loader/filetypes/TilemapJSONFile.js index cbe9e4f3c..90d7d2392 100644 --- a/src/loader/filetypes/TilemapJSONFile.js +++ b/src/loader/filetypes/TilemapJSONFile.js @@ -1,4 +1,8 @@ +var FileTypesManager = require('../FileTypesManager'); var JSONFile = require('./JSONFile.js'); +var TILEMAP_FORMATS = require('../../gameobjects/tilemap/Formats'); + +// Phaser.Loader.FileTypes.TilemapJSONFile var TilemapJSONFile = function (key, url, path, format, xhrSettings) { @@ -12,23 +16,48 @@ var TilemapJSONFile = function (key, url, path, format, xhrSettings) return json; }; -TilemapJSONFile.create = function (loader, key, url, format, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('tilemapTiledJSON', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(TilemapJSONFile(key[i], url, loader.path, format, xhrSettings)); + this.addFile(TilemapJSONFile(key[i], url, this.path, TILEMAP_FORMATS.TILED_JSON, xhrSettings)); } } else { - loader.addFile(TilemapJSONFile(key, url, loader.path, format, xhrSettings)); + this.addFile(TilemapJSONFile(key, url, this.path, TILEMAP_FORMATS.TILED_JSON, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); + +FileTypesManager.register('tilemapWeltmeister', function (key, url, xhrSettings) +{ + if (Array.isArray(key)) + { + for (var i = 0; i < key.length; i++) + { + // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object + this.addFile(TilemapJSONFile(key[i], url, this.path, TILEMAP_FORMATS.WELTMEISTER.TILED_JSON, xhrSettings)); + } + } + else + { + this.addFile(TilemapJSONFile(key, url, this.path, TILEMAP_FORMATS.WELTMEISTER.TILED_JSON, xhrSettings)); + } + + // For method chaining + return this; +}); module.exports = TilemapJSONFile; diff --git a/src/loader/filetypes/UnityAtlasFile.js b/src/loader/filetypes/UnityAtlasFile.js index 856d0c9b8..5c1b12ee8 100644 --- a/src/loader/filetypes/UnityAtlasFile.js +++ b/src/loader/filetypes/UnityAtlasFile.js @@ -1,3 +1,4 @@ +var FileTypesManager = require('../FileTypesManager'); var ImageFile = require('./ImageFile.js'); var TextFile = require('./TextFile.js'); @@ -17,4 +18,22 @@ var UnityAtlasFile = function (key, textureURL, atlasURL, path, textureXhrSettin return { texture: image, data: data }; }; +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('unityAtlas', function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) +{ + // Returns an object with two properties: 'texture' and 'data' + var files = new UnityAtlasFile(key, textureURL, atlasURL, this.path, textureXhrSettings, atlasXhrSettings); + + this.addFile(files.texture); + this.addFile(files.data); + + return this; + +}); + module.exports = UnityAtlasFile; diff --git a/src/loader/filetypes/WavefrontFile.js b/src/loader/filetypes/WavefrontFile.js index 269d6eff7..5e3c490ec 100644 --- a/src/loader/filetypes/WavefrontFile.js +++ b/src/loader/filetypes/WavefrontFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); var ParseOBJ = require('../../geom/mesh/ParseOBJ'); @@ -42,23 +43,29 @@ var WavefrontFile = new Class({ }); -WavefrontFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('obj', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new WavefrontFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new WavefrontFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new WavefrontFile(key, url, loader.path, xhrSettings)); + this.addFile(new WavefrontFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = WavefrontFile; diff --git a/src/loader/filetypes/XMLFile.js b/src/loader/filetypes/XMLFile.js index 7da8e542c..6e40a61bf 100644 --- a/src/loader/filetypes/XMLFile.js +++ b/src/loader/filetypes/XMLFile.js @@ -1,6 +1,7 @@ var Class = require('../../utils/Class'); var CONST = require('../const'); var File = require('../File'); +var FileTypesManager = require('../FileTypesManager'); var GetFastValue = require('../../utils/object/GetFastValue'); var ParseXML = require('../../dom/ParseXML'); @@ -47,23 +48,29 @@ var XMLFile = new Class({ }); -XMLFile.create = function (loader, key, url, xhrSettings) +// When registering a factory function 'this' refers to the Loader context. +// +// There are several properties available to use: +// +// this.scene - a reference to the Scene that owns the GameObjectFactory + +FileTypesManager.register('xml', function (key, url, xhrSettings) { if (Array.isArray(key)) { for (var i = 0; i < key.length; i++) { // If it's an array it has to be an array of Objects, so we get everything out of the 'key' object - loader.addFile(new XMLFile(key[i], url, loader.path, xhrSettings)); + this.addFile(new XMLFile(key[i], url, this.path, xhrSettings)); } } else { - loader.addFile(new XMLFile(key, url, loader.path, xhrSettings)); + this.addFile(new XMLFile(key, url, this.path, xhrSettings)); } // For method chaining - return loader; -}; + return this; +}); module.exports = XMLFile; diff --git a/src/loader/index.js b/src/loader/index.js index 5f9553ee5..cedfcefa5 100644 --- a/src/loader/index.js +++ b/src/loader/index.js @@ -4,6 +4,29 @@ module.exports = { BaseLoader: require('./BaseLoader'), File: require('./File'), - LoaderPlugin: require('./Loader') + FileTypesManager: require('./FileTypesManager'), + LoaderPlugin: require('./Loader'), + + FileTypes: { + AnimationJSONFile: require('./filetypes/AnimationJSONFile'), + AtlasJSONFile: require('./filetypes/AtlasJSONFile'), + AudioFile: require('./filetypes/AudioFile'), + BinaryFile: require('./filetypes/BinaryFile'), + BitmapFontFile: require('./filetypes/BitmapFontFile'), + GLSLFile: require('./filetypes/GLSLFile'), + HTMLFile: require('./filetypes/HTMLFile'), + ImageFile: require('./filetypes/ImageFile'), + JSONFile: require('./filetypes/JSONFile'), + PluginFile: require('./filetypes/PluginFile'), + ScriptFile: require('./filetypes/ScriptFile'), + SpriteSheet: require('./filetypes/SpriteSheet'), + SVGFile: require('./filetypes/SVGFile'), + TextFile: require('./filetypes/TextFile'), + TilemapCSVFile: require('./filetypes/TilemapCSVFile'), + TilemapJSONFile: require('./filetypes/TilemapJSONFile'), + UnityAtlasFile: require('./filetypes/UnityAtlasFile'), + WavefrontFile: require('./filetypes/WavefrontFile'), + XMLFile: require('./filetypes/XMLFile') + } }; From 8983c93fc6c9c83b92af238e840e557aac17aa27 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 13:51:12 +0000 Subject: [PATCH 095/115] Added AudioSprite loader. --- src/loader/filetypes/AudioFile.js | 59 +++++++++++++++-------------- src/loader/filetypes/AudioSprite.js | 44 +++++++++++++++++++++ 2 files changed, 75 insertions(+), 28 deletions(-) create mode 100644 src/loader/filetypes/AudioSprite.js diff --git a/src/loader/filetypes/AudioFile.js b/src/loader/filetypes/AudioFile.js index 738645e2d..3f92609f4 100644 --- a/src/loader/filetypes/AudioFile.js +++ b/src/loader/filetypes/AudioFile.js @@ -59,6 +59,36 @@ var AudioFile = new Class({ }); +AudioFile.create = function (loader, key, urls, config, xhrSettings) +{ + var game = loader.systems.game; + var audioConfig = game.config.audio; + var deviceAudio = game.device.Audio; + + if ((audioConfig && audioConfig.noAudio) || (!deviceAudio.webAudio && !deviceAudio.audioData)) + { + console.info('Skipping loading audio \'' + key + '\' since sounds are disabled.'); + return null; + } + + var url = AudioFile.findAudioURL(game, urls); + + if (!url) + { + console.warn('No supported url provided for audio \'' + key + '\'!'); + return null; + } + + if (deviceAudio.webAudio && !(audioConfig && audioConfig.disableWebAudio)) + { + return new AudioFile(key, url, this.path, xhrSettings, game.sound.context); + } + else + { + return new HTML5AudioFile(key, url, this.path, config); + } +}; + // When registering a factory function 'this' refers to the Loader context. // // There are several properties available to use: @@ -67,34 +97,7 @@ var AudioFile = new Class({ FileTypesManager.register('audio', function (key, urls, config, xhrSettings) { - var game = this.systems.game; - var audioConfig = game.config.audio; - var deviceAudio = game.device.Audio; - - if ((audioConfig && audioConfig.noAudio) || (!deviceAudio.webAudio && !deviceAudio.audioData)) - { - console.info('Skipping loading audio \'' + key + '\' since sounds are disabled.'); - return this; - } - - var url = AudioFile.findAudioURL(game, urls); - - if (!url) - { - console.warn('No supported url provided for audio \'' + key + '\'!'); - return this; - } - - var audioFile; - - if (deviceAudio.webAudio && !(audioConfig && audioConfig.disableWebAudio)) - { - audioFile = new AudioFile(key, url, this.path, xhrSettings, game.sound.context); - } - else - { - audioFile = new HTML5AudioFile(key, url, this.path, config); - } + var audioFile = AudioFile.create(this, key, urls, config, xhrSettings); if (audioFile) { diff --git a/src/loader/filetypes/AudioSprite.js b/src/loader/filetypes/AudioSprite.js new file mode 100644 index 000000000..2cd02975e --- /dev/null +++ b/src/loader/filetypes/AudioSprite.js @@ -0,0 +1,44 @@ +var AudioFile = require('./AudioFile.js'); +var CONST = require('../const'); +var FileTypesManager = require('../FileTypesManager'); +var JSONFile = require('./JSONFile.js'); + +// Phaser.Loader.FileTypes.AudioSprite + +FileTypesManager.register('audioSprite', function (key, urls, json, config, audioXhrSettings, jsonXhrSettings) +{ + var audioFile = AudioFile.create(this, key, urls, config, audioXhrSettings); + + if (audioFile) + { + var jsonFile; + + if (typeof json === 'string') + { + jsonFile = new JSONFile(key, json, this.path, jsonXhrSettings); + + this.addFile(jsonFile); + } + else + { + jsonFile = { + type: 'json', + key: key, + data: json, + state: CONST.FILE_WAITING_LINKFILE + }; + } + + // Link them together + audioFile.linkFile = jsonFile; + jsonFile.linkFile = audioFile; + + // Set the type + audioFile.linkType = 'audioSprite'; + jsonFile.linkType = 'audioSprite'; + + this.addFile(audioFile); + } + + return this; +}); From f5462146e2a52b1f8f668d26d349c45309f497e3 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 13:51:20 +0000 Subject: [PATCH 096/115] Added MultiAtlas loader. --- src/loader/filetypes/MultiAtlas.js | 60 ++++++++++++++++++++++++++++++ src/loader/index.js | 2 + 2 files changed, 62 insertions(+) create mode 100644 src/loader/filetypes/MultiAtlas.js diff --git a/src/loader/filetypes/MultiAtlas.js b/src/loader/filetypes/MultiAtlas.js new file mode 100644 index 000000000..4feb7b390 --- /dev/null +++ b/src/loader/filetypes/MultiAtlas.js @@ -0,0 +1,60 @@ +var FileTypesManager = require('../FileTypesManager'); +var ImageFile = require('./ImageFile.js'); +var JSONFile = require('./JSONFile.js'); +var NumberArray = require('../utils/array/NumberArray'); + +// Phaser.Loader.FileTypes.MultiAtlas + +FileTypesManager.register('multiatlas', function (key, textureURLs, atlasURLs, textureXhrSettings, atlasXhrSettings) +{ + if (typeof textureURLs === 'number') + { + var total = textureURLs; + var suffix = (atlasURLs === undefined) ? '' : atlasURLs; + + textureURLs = NumberArray(0, total, key + suffix, '.png'); + atlasURLs = NumberArray(0, total, key + suffix, '.json'); + } + else + { + if (!Array.isArray(textureURLs)) + { + textureURLs = [ textureURLs ]; + } + + if (!Array.isArray(atlasURLs)) + { + atlasURLs = [ atlasURLs ]; + } + } + + var file; + var i = 0; + var multiKey; + + this._multilist[key] = []; + + for (i = 0; i < textureURLs.length; i++) + { + multiKey = '_MA_IMG_' + key + '_' + i.toString(); + + file = new ImageFile(multiKey, textureURLs[i], this.path, textureXhrSettings); + + this.addFile(file); + + this._multilist[key].push(multiKey); + } + + for (i = 0; i < atlasURLs.length; i++) + { + multiKey = '_MA_JSON_' + key + '_' + i.toString(); + + file = new JSONFile(multiKey, atlasURLs[i], this.path, atlasXhrSettings); + + this.addFile(file); + + this._multilist[key].push(multiKey); + } + + return this; +}); diff --git a/src/loader/index.js b/src/loader/index.js index cedfcefa5..6f8eb7c19 100644 --- a/src/loader/index.js +++ b/src/loader/index.js @@ -11,12 +11,14 @@ module.exports = { AnimationJSONFile: require('./filetypes/AnimationJSONFile'), AtlasJSONFile: require('./filetypes/AtlasJSONFile'), AudioFile: require('./filetypes/AudioFile'), + AudioSprite: require('./filetypes/AudioSprite'), BinaryFile: require('./filetypes/BinaryFile'), BitmapFontFile: require('./filetypes/BitmapFontFile'), GLSLFile: require('./filetypes/GLSLFile'), HTMLFile: require('./filetypes/HTMLFile'), ImageFile: require('./filetypes/ImageFile'), JSONFile: require('./filetypes/JSONFile'), + MultiAtlas: require('./filetypes/MultiAtlas'), PluginFile: require('./filetypes/PluginFile'), ScriptFile: require('./filetypes/ScriptFile'), SpriteSheet: require('./filetypes/SpriteSheet'), From e18858010c40c5cdcd5b2fbf66a621e8acf8594e Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 13:52:03 +0000 Subject: [PATCH 097/115] Tidying up before merging with BaseLoader. --- src/loader/Loader.js | 234 ------------------------------------------- 1 file changed, 234 deletions(-) diff --git a/src/loader/Loader.js b/src/loader/Loader.js index cb2f95300..fc1671001 100644 --- a/src/loader/Loader.js +++ b/src/loader/Loader.js @@ -1,8 +1,6 @@ var BaseLoader = require('./BaseLoader'); var Class = require('../utils/Class'); -var CONST = require('./const'); var FileTypesManager = require('./FileTypesManager'); -var NumberArray = require('../utils/array/NumberArray'); var PluginManager = require('../plugins/PluginManager'); var Loader = new Class({ @@ -36,238 +34,6 @@ var Loader = new Class({ eventEmitter.on('destroy', this.destroy, this); }, - // key can be either a string, an object or an array of objects - - /* - image: function (key, url, xhrSettings) - { - return ImageFile.create(this, key, url, xhrSettings); - }, - - animation: function (key, url, xhrSettings) - { - return AnimationJSONFile.create(this, key, url, xhrSettings); - }, - - json: function (key, url, xhrSettings) - { - return JSONFile.create(this, key, url, xhrSettings); - }, - - script: function (key, url, xhrSettings) - { - return ScriptFile.create(this, key, url, xhrSettings); - }, - - plugin: function (key, url, xhrSettings) - { - return PluginFile.create(this, key, url, xhrSettings); - }, - - xml: function (key, url, xhrSettings) - { - return XMLFile.create(this, key, url, xhrSettings); - }, - - /* - binary: function (key, url, xhrSettings) - { - return BinaryFile.create(this, key, url, xhrSettings); - }, - - text: function (key, url, xhrSettings) - { - return TextFile.create(this, key, url, xhrSettings); - }, - - glsl: function (key, url, xhrSettings) - { - return GLSLFile.create(this, key, url, xhrSettings); - }, - - html: function (key, url, width, height, xhrSettings) - { - return HTMLFile.create(this, key, url, width, height, xhrSettings); - }, - - svg: function (key, url, xhrSettings) - { - return SVGFile.create(this, key, url, xhrSettings); - }, - - obj: function (key, url, xhrSettings) - { - return WavefrontFile.create(this, key, url, xhrSettings); - }, - - // config can include: frameWidth, frameHeight, startFrame, endFrame, margin, spacing - spritesheet: function (key, url, config, xhrSettings) - { - return SpriteSheet.create(this, key, url, config, xhrSettings); - }, - */ - - // config can include: instances - /* - audio: function (key, urls, config, xhrSettings) - { - var audioFile = AudioFile.create(this, key, urls, config, xhrSettings); - - if(audioFile) - { - this.addFile(audioFile); - } - - return this; - }, - */ - - /* - tilemapCSV: function (key, url, xhrSettings) - { - return TilemapCSVFile.create(this, key, url, TILEMAP_FORMATS.CSV, xhrSettings); - }, - - tilemapTiledJSON: function (key, url, xhrSettings) - { - return TilemapJSONFile.create(this, key, url, TILEMAP_FORMATS.TILED_JSON, xhrSettings); - }, - - tilemapWeltmeister: function (key, url, xhrSettings) - { - return TilemapJSONFile.create(this, key, url, TILEMAP_FORMATS.WELTMEISTER, xhrSettings); - }, - */ - - // --------------------------------------------------- - // Multi-File Loaders - // --------------------------------------------------- - - audioSprite: function (key, urls, json, config, audioXhrSettings, jsonXhrSettings) - { - var audioFile = AudioFile.create(this, key, urls, config, audioXhrSettings); - - if(audioFile) - { - var jsonFile; - - if (typeof json === 'string') - { - jsonFile = new JSONFile(key, json, this.path, jsonXhrSettings); - - this.addFile(jsonFile); - } - else - { - jsonFile = { - type: 'json', - key: key, - data: json, - state: CONST.FILE_WAITING_LINKFILE - }; - } - - // Link them together - audioFile.linkFile = jsonFile; - jsonFile.linkFile = audioFile; - - // Set the type - audioFile.linkType = 'audioSprite'; - jsonFile.linkType = 'audioSprite'; - - this.addFile(audioFile); - } - - return this; - }, - - /* - unityAtlas: function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) - { - // Returns an object with two properties: 'texture' and 'data' - var files = new UnityAtlasFile(key, textureURL, atlasURL, this.path, textureXhrSettings, atlasXhrSettings); - - this.addFile(files.texture); - this.addFile(files.data); - - return this; - }, - - atlas: function (key, textureURL, atlasURL, textureXhrSettings, atlasXhrSettings) - { - // Returns an object with two properties: 'texture' and 'data' - var files = new AtlasJSONFile(key, textureURL, atlasURL, this.path, textureXhrSettings, atlasXhrSettings); - - this.addFile(files.texture); - this.addFile(files.data); - - return this; - }, - - bitmapFont: function (key, textureURL, xmlURL, textureXhrSettings, xmlXhrSettings) - { - // Returns an object with two properties: 'texture' and 'data' - var files = new BitmapFontFile(key, textureURL, xmlURL, this.path, textureXhrSettings, xmlXhrSettings); - - this.addFile(files.texture); - this.addFile(files.data); - - return this; - }, - */ - - multiatlas: function (key, textureURLs, atlasURLs, textureXhrSettings, atlasXhrSettings) - { - if (typeof textureURLs === 'number') - { - var total = textureURLs; - var suffix = (atlasURLs === undefined) ? '' : atlasURLs; - - textureURLs = NumberArray(0, total, key + suffix, '.png'); - atlasURLs = NumberArray(0, total, key + suffix, '.json'); - } - else - { - if (!Array.isArray(textureURLs)) - { - textureURLs = [ textureURLs ]; - } - - if (!Array.isArray(atlasURLs)) - { - atlasURLs = [ atlasURLs ]; - } - } - - var file; - var i = 0; - var multiKey; - - this._multilist[key] = []; - - for (i = 0; i < textureURLs.length; i++) - { - multiKey = '_MA_IMG_' + key + '_' + i.toString(); - - file = new ImageFile(multiKey, textureURLs[i], this.path, textureXhrSettings); - - this.addFile(file); - - this._multilist[key].push(multiKey); - } - - for (i = 0; i < atlasURLs.length; i++) - { - multiKey = '_MA_JSON_' + key + '_' + i.toString(); - - file = new JSONFile(multiKey, atlasURLs[i], this.path, atlasXhrSettings); - - this.addFile(file); - - this._multilist[key].push(multiKey); - } - }, - loadArray: function (files) { if (Array.isArray(files)) From 4aa6e931f1bf1f65612c4ed5fb57a6d4bb1d9717 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 14:47:16 +0000 Subject: [PATCH 098/115] Merging Loader into BaseLoader --- src/loader/BaseLoader.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/loader/BaseLoader.js b/src/loader/BaseLoader.js index 4b6bb799e..30ee10713 100644 --- a/src/loader/BaseLoader.js +++ b/src/loader/BaseLoader.js @@ -4,6 +4,8 @@ var CustomSet = require('../structs/Set'); var EventEmitter = require('eventemitter3'); var ParseXMLBitmapFont = require('../gameobjects/bitmaptext/ParseXMLBitmapFont'); var XHRSettings = require('./XHRSettings'); +var FileTypesManager = require('./FileTypesManager'); +var PluginManager = require('../plugins/PluginManager'); // Phaser.Loader.BaseLoader @@ -23,6 +25,18 @@ var BaseLoader = new Class({ this.scene = scene; + this.systems = scene.sys; + + if (!scene.sys.settings.isBooted) + { + scene.sys.events.once('boot', this.boot, this); + } + + this._multilist = {}; + + // Inject the available filetypes into the Loader + FileTypesManager.install(this); + // Move to a 'setURL' method? this.baseURL = ''; this.path = ''; @@ -45,6 +59,14 @@ var BaseLoader = new Class({ this.state = CONST.LOADER_IDLE; }, + boot: function () + { + var eventEmitter = this.systems.events; + + eventEmitter.on('shutdown', this.shutdown, this); + eventEmitter.on('destroy', this.destroy, this); + }, + setPath: function (path) { if (path.substr(-1) !== '/') @@ -514,4 +536,6 @@ var BaseLoader = new Class({ }); +PluginManager.register('Loader', Loader, 'load'); + module.exports = BaseLoader; From e2d71e2c6dd083e113c90edd0c97de1222e4eb10 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 14:54:50 +0000 Subject: [PATCH 099/115] BaseLoader renamed LoaderPlugin, const updated, index updated. --- src/loader/Loader.js | 94 ------------------- src/loader/{BaseLoader.js => LoaderPlugin.js} | 32 ++++--- src/loader/const.js | 38 ++++++-- src/loader/filetypes/MultiAtlas.js | 2 +- src/loader/index.js | 3 +- 5 files changed, 47 insertions(+), 122 deletions(-) delete mode 100644 src/loader/Loader.js rename src/loader/{BaseLoader.js => LoaderPlugin.js} (95%) diff --git a/src/loader/Loader.js b/src/loader/Loader.js deleted file mode 100644 index fc1671001..000000000 --- a/src/loader/Loader.js +++ /dev/null @@ -1,94 +0,0 @@ -var BaseLoader = require('./BaseLoader'); -var Class = require('../utils/Class'); -var FileTypesManager = require('./FileTypesManager'); -var PluginManager = require('../plugins/PluginManager'); - -var Loader = new Class({ - - Extends: BaseLoader, - - initialize: - - function Loader (scene) - { - BaseLoader.call(this, scene); - - this.systems = scene.sys; - - if (!scene.sys.settings.isBooted) - { - scene.sys.events.once('boot', this.boot, this); - } - - this._multilist = {}; - - // Inject the available filetypes into the Loader - FileTypesManager.install(this); - }, - - boot: function () - { - var eventEmitter = this.systems.events; - - eventEmitter.on('shutdown', this.shutdown, this); - eventEmitter.on('destroy', this.destroy, this); - }, - - loadArray: function (files) - { - if (Array.isArray(files)) - { - for (var i = 0; i < files.length; i++) - { - this.file(files[i]); - } - } - - return (this.list.size > 0); - }, - - file: function (file) - { - var entry; - - switch (file.type) - { - case 'spritesheet': - entry = this.spritesheet(file.key, file.url, file.config, file.xhrSettings); - break; - - case 'atlas': - entry = this.atlas(file.key, file.textureURL, file.atlasURL, file.textureXhrSettings, file.atlasXhrSettings); - break; - - case 'bitmapFont': - entry = this.bitmapFont(file.key, file.textureURL, file.xmlURL, file.textureXhrSettings, file.xmlXhrSettings); - break; - - case 'multiatlas': - entry = this.multiatlas(file.key, file.textureURLs, file.atlasURLs, file.textureXhrSettings, file.atlasXhrSettings); - break; - - case 'audioSprite': - entry = this.audioSprite(file.key, file.urls, file.json, file.config, file.audioXhrSettings, file.jsonXhrSettings); - break; - - // image, json, xml, binary, text, glsl, svg, obj - default: - entry = this[file.type](file.key, file.url, file.xhrSettings); - break; - } - - return entry; - }, - - shutdown: function () - { - // TODO - } - -}); - -PluginManager.register('Loader', Loader, 'load'); - -module.exports = Loader; diff --git a/src/loader/BaseLoader.js b/src/loader/LoaderPlugin.js similarity index 95% rename from src/loader/BaseLoader.js rename to src/loader/LoaderPlugin.js index 30ee10713..6fdaf5666 100644 --- a/src/loader/BaseLoader.js +++ b/src/loader/LoaderPlugin.js @@ -2,24 +2,20 @@ var Class = require('../utils/Class'); var CONST = require('./const'); var CustomSet = require('../structs/Set'); var EventEmitter = require('eventemitter3'); -var ParseXMLBitmapFont = require('../gameobjects/bitmaptext/ParseXMLBitmapFont'); -var XHRSettings = require('./XHRSettings'); var FileTypesManager = require('./FileTypesManager'); +var ParseXMLBitmapFont = require('../gameobjects/bitmaptext/ParseXMLBitmapFont'); var PluginManager = require('../plugins/PluginManager'); +var XHRSettings = require('./XHRSettings'); -// Phaser.Loader.BaseLoader +// Phaser.Loader.LoaderPlugin -// To finish the loader ... -// -// 3) Progress update - -var BaseLoader = new Class({ +var LoaderPlugin = new Class({ Extends: EventEmitter, initialize: - function BaseLoader (scene) + function LoaderPlugin (scene) { EventEmitter.call(this); @@ -107,7 +103,7 @@ var BaseLoader = new Class({ start: function () { - console.log(this.scene.sys.settings.key, '- BaseLoader start. Files to load:', this.list.size); + console.log(this.scene.sys.settings.key, '- LoaderPlugin start. Files to load:', this.list.size); if (!this.isReady()) { @@ -143,7 +139,7 @@ var BaseLoader = new Class({ processLoadQueue: function () { - // console.log('======== BaseLoader processLoadQueue'); + // console.log('======== LoaderPlugin processLoadQueue'); // console.log('List size', this.list.size); // console.log(this.inflight.size, 'items still in flight. Can load another', (this.maxParallelDownloads - this.inflight.size)); @@ -213,7 +209,7 @@ var BaseLoader = new Class({ finishedLoading: function () { - // console.log('---> BaseLoader.finishedLoading PROCESSING', this.queue.size, 'files'); + // console.log('---> LoaderPlugin.finishedLoading PROCESSING', this.queue.size, 'files'); if(this.state === CONST.LOADER_PROCESSING) { @@ -496,7 +492,7 @@ var BaseLoader = new Class({ if (filename === undefined) { filename = 'file.json'; } if (filetype === undefined) { filetype = 'application/json'; } - var blob = new Blob([data], { type: filetype }); + var blob = new Blob([ data ], { type: filetype }); var url = URL.createObjectURL(blob); @@ -528,6 +524,12 @@ var BaseLoader = new Class({ this.state = CONST.LOADER_IDLE; }, + shutdown: function () + { + this.reset(); + this.state = CONST.LOADER_SHUTDOWN; + }, + destroy: function () { this.reset(); @@ -536,6 +538,6 @@ var BaseLoader = new Class({ }); -PluginManager.register('Loader', Loader, 'load'); +PluginManager.register('Loader', LoaderPlugin, 'load'); -module.exports = BaseLoader; +module.exports = LoaderPlugin; diff --git a/src/loader/const.js b/src/loader/const.js index d9dcdb6dd..d609e5136 100644 --- a/src/loader/const.js +++ b/src/loader/const.js @@ -4,17 +4,35 @@ var FILE_CONST = { LOADER_LOADING: 1, LOADER_PROCESSING: 2, LOADER_COMPLETE: 3, - LOADER_DESTROYED: 4, + LOADER_SHUTDOWN: 4, + LOADER_DESTROYED: 5, - FILE_PENDING: 5, // file is in the load queue but not yet started - FILE_LOADING: 6, // file has been started to load by the loader (onLoad called) - FILE_LOADED: 7, // file has loaded successfully, awaiting processing - FILE_FAILED: 8, // file failed to load - FILE_PROCESSING: 9, // file is being processed (onProcess callback) - FILE_WAITING_LINKFILE: 10, // file is being processed (onProcess callback) - FILE_ERRORED: 11, // file is being processed (onProcess callback) - FILE_COMPLETE: 12, // file has finished processing - FILE_DESTROYED: 13, // file has been destroyed + // File is in the load queue but not yet started + FILE_PENDING: 10, + + // File has been started to load by the loader (onLoad called) + FILE_LOADING: 11, + + // File has loaded successfully, awaiting processing + FILE_LOADED: 12, + + // File failed to load + FILE_FAILED: 13, + + // File is being processed (onProcess callback) + FILE_PROCESSING: 14, + + // File is being processed (onProcess callback) + FILE_WAITING_LINKFILE: 15, + + // File is being processed (onProcess callback) + FILE_ERRORED: 16, + + // File has finished processing + FILE_COMPLETE: 17, + + // File has been destroyed + FILE_DESTROYED: 18, TEXTURE_ATLAS_JSON_ARRAY: 20, TEXTURE_ATLAS_JSON_HASH: 21 diff --git a/src/loader/filetypes/MultiAtlas.js b/src/loader/filetypes/MultiAtlas.js index 4feb7b390..bc042f557 100644 --- a/src/loader/filetypes/MultiAtlas.js +++ b/src/loader/filetypes/MultiAtlas.js @@ -1,7 +1,7 @@ var FileTypesManager = require('../FileTypesManager'); var ImageFile = require('./ImageFile.js'); var JSONFile = require('./JSONFile.js'); -var NumberArray = require('../utils/array/NumberArray'); +var NumberArray = require('../../utils/array/NumberArray'); // Phaser.Loader.FileTypes.MultiAtlas diff --git a/src/loader/index.js b/src/loader/index.js index 6f8eb7c19..200160121 100644 --- a/src/loader/index.js +++ b/src/loader/index.js @@ -2,10 +2,9 @@ module.exports = { - BaseLoader: require('./BaseLoader'), + LoaderPlugin: require('./LoaderPlugin'), File: require('./File'), FileTypesManager: require('./FileTypesManager'), - LoaderPlugin: require('./Loader'), FileTypes: { AnimationJSONFile: require('./filetypes/AnimationJSONFile'), From 999b7d96df5c36b5cf4570085a5cd38549b79cb8 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Fri, 19 Jan 2018 16:24:26 +0100 Subject: [PATCH 100/115] skipping looping and ending logic if current time is 0 since some HTML5 Audio implementations set currentTime value to 0 when changing playback rate or performing any other operation on an audio tag object --- src/sound/html5/HTML5AudioSound.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 4750430ed..171083da6 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -213,10 +213,17 @@ var HTML5AudioSound = new Class({ } return; } + var currentTime = this.audio.currentTime; + // skipping looping and ending logic if current time is 0 + // since some HTML5 Audio implementations set currentTime + // value to 0 when changing playback rate or performing any + // other operation on an audio tag object + if (currentTime === 0) { + return; + } // handle looping and ending var startTime = this.currentMarker ? this.currentMarker.start : 0; var endTime = startTime + this.duration; - var currentTime = this.audio.currentTime; if (this.currentConfig.loop) { if (currentTime >= endTime - this.manager.loopEndOffset) { this.audio.currentTime = startTime + Math.max(0, currentTime - endTime); From ac7be301f16c86cabaa68c46fa0927369b979806 Mon Sep 17 00:00:00 2001 From: Pavle Goloskokovic Date: Fri, 19 Jan 2018 17:12:49 +0100 Subject: [PATCH 101/115] Reverting previous commit since it did not fix the issue --- src/sound/html5/HTML5AudioSound.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/sound/html5/HTML5AudioSound.js b/src/sound/html5/HTML5AudioSound.js index 171083da6..4750430ed 100644 --- a/src/sound/html5/HTML5AudioSound.js +++ b/src/sound/html5/HTML5AudioSound.js @@ -213,17 +213,10 @@ var HTML5AudioSound = new Class({ } return; } - var currentTime = this.audio.currentTime; - // skipping looping and ending logic if current time is 0 - // since some HTML5 Audio implementations set currentTime - // value to 0 when changing playback rate or performing any - // other operation on an audio tag object - if (currentTime === 0) { - return; - } // handle looping and ending var startTime = this.currentMarker ? this.currentMarker.start : 0; var endTime = startTime + this.duration; + var currentTime = this.audio.currentTime; if (this.currentConfig.loop) { if (currentTime >= endTime - this.manager.loopEndOffset) { this.audio.currentTime = startTime + Math.max(0, currentTime - endTime); From 13ed054d7914fd4899762da8c1c5cdbec7820f47 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 16:28:32 +0000 Subject: [PATCH 102/115] Removed display of checksum. --- src/boot/DebugHeader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/DebugHeader.js b/src/boot/DebugHeader.js index a4fa4413e..a03ccc5ea 100644 --- a/src/boot/DebugHeader.js +++ b/src/boot/DebugHeader.js @@ -105,7 +105,7 @@ var DebugHeader = function (game) } // Keep this during dev build only - console.log(CHECKSUM.build); + // console.log(CHECKSUM.build); }; module.exports = DebugHeader; From 57444596e523f6182b92c2d2b1ed924afdaa0d2d Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 16:28:59 +0000 Subject: [PATCH 103/115] Loader now emits a progress event which can be used for progress bar loaders, etc. Also added `setBasePath` and removed console logs. --- src/loader/LoaderPlugin.js | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index 6fdaf5666..9e12009d8 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -33,7 +33,6 @@ var LoaderPlugin = new Class({ // Inject the available filetypes into the Loader FileTypesManager.install(this); - // Move to a 'setURL' method? this.baseURL = ''; this.path = ''; @@ -46,6 +45,9 @@ var LoaderPlugin = new Class({ this.crossOrigin = undefined; + this.totalToLoad = 0; + this.progress = 0; + this.list = new CustomSet(); this.inflight = new CustomSet(); this.failed = new CustomSet(); @@ -57,12 +59,23 @@ var LoaderPlugin = new Class({ boot: function () { + // Set values from scene / game configs + + + var eventEmitter = this.systems.events; eventEmitter.on('shutdown', this.shutdown, this); eventEmitter.on('destroy', this.destroy, this); }, + setBaseURL: function (url) + { + this.baseURL = url; + + return this; + }, + setPath: function (path) { if (path.substr(-1) !== '/') @@ -103,13 +116,16 @@ var LoaderPlugin = new Class({ start: function () { - console.log(this.scene.sys.settings.key, '- LoaderPlugin start. Files to load:', this.list.size); + // console.log(this.scene.sys.settings.key, '- Loader start. Files to load:', this.list.size); if (!this.isReady()) { return; } + this.progress = 0; + this.totalToLoad = this.list.size; + this.emit('start', this); if (this.list.size === 0) @@ -134,7 +150,9 @@ var LoaderPlugin = new Class({ updateProgress: function () { + this.progress = 1 - (this.list.size / this.totalToLoad); + this.emit('progress', this.progress); }, processLoadQueue: function () @@ -186,15 +204,19 @@ var LoaderPlugin = new Class({ if (success) { + this.emit('load', previousFile); this.queue.set(previousFile); } else { + this.emit('loaderror', previousFile); this.failed.set(previousFile); } this.inflight.delete(previousFile); + this.updateProgress(); + if (this.list.size > 0) { // console.log('nextFile - still something in the list'); @@ -211,11 +233,13 @@ var LoaderPlugin = new Class({ { // console.log('---> LoaderPlugin.finishedLoading PROCESSING', this.queue.size, 'files'); - if(this.state === CONST.LOADER_PROCESSING) + if (this.state === CONST.LOADER_PROCESSING) { return; } + this.progress = 1; + this.state = CONST.LOADER_PROCESSING; this.storage.clear(); @@ -223,7 +247,6 @@ var LoaderPlugin = new Class({ this.queue.each(function (file) { // console.log('%c Calling process on ' + file.key, 'color: #000000; background: #ffff00;'); - file.onProcess(this.processUpdate.bind(this)); }, this); }, @@ -284,7 +307,7 @@ var LoaderPlugin = new Class({ processComplete: function () { - console.log(this.scene.sys.settings.key, '- Loader Complete. Loaded:', this.storage.size, 'Failed:', this.failed.size); + // console.log(this.scene.sys.settings.key, '- Loader Complete. Loaded:', this.storage.size, 'Failed:', this.failed.size); this.list.clear(); this.inflight.clear(); @@ -515,6 +538,8 @@ var LoaderPlugin = new Class({ this.storage.clear(); this.removeAllListeners('start'); + this.removeAllListeners('load'); + this.removeAllListeners('loaderror'); this.removeAllListeners('complete'); this.tag = ''; From 25089f66fd0a78d5423725b1ffb3bb756416650f Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 16:29:25 +0000 Subject: [PATCH 104/115] Scene will now be made active as soon as it has init'd, not after the load is complete. This allows a scene to render while loading assets. --- src/scene/SceneManager.js | 66 +++++++++++---------------------------- 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/src/scene/SceneManager.js b/src/scene/SceneManager.js index 5b8fdb14f..47ba18bfd 100644 --- a/src/scene/SceneManager.js +++ b/src/scene/SceneManager.js @@ -105,6 +105,14 @@ var SceneManager = new Class({ scene.init.call(scene, scene.sys.settings.data); } + // Insert at the correct index, or it just all goes wrong :) + var i = this.getSceneIndex(scene); + + this.active.push({ index: i, scene: scene }); + + // Sort the 'active' array based on the index property + this.active.sort(this.sortScenes); + var loader; if (scene.sys.load) @@ -126,7 +134,6 @@ var SceneManager = new Class({ else { // Start the loader going as we have something in the queue - loader.once('complete', this.loadComplete, this); loader.start(); @@ -260,15 +267,6 @@ var SceneManager = new Class({ */ create: function (scene) { - // Insert at the correct index, or it just all goes wrong :) - - var i = this.getSceneIndex(scene); - - this.active.push({ index: i, scene: scene }); - - // Sort the 'active' array based on the index property - this.active.sort(this.sortScenes); - if (scene.create) { scene.create.call(scene, scene.sys.settings.data); @@ -354,42 +352,11 @@ var SceneManager = new Class({ this.createSceneDisplay(newScene); - // Default required functions - - /* - if (!newScene.init) - { - newScene.init = NOOP; - } - - if (!newScene.preload) - { - newScene.preload = NOOP; - } - - if (!newScene.create) - { - newScene.create = NOOP; - } - - if (!newScene.shutdown) - { - newScene.shutdown = NOOP; - } - */ - if (!newScene.update) { newScene.update = NOOP; } - /* - if (!newScene.render) - { - newScene.render = NOOP; - } - */ - return newScene; } }, @@ -455,21 +422,27 @@ var SceneManager = new Class({ this.createSceneDisplay(newScene); - // Extract callbacks or set NOOP + // Extract callbacks - var defaults = [ 'init', 'preload', 'create', 'update', 'render' ]; + var defaults = [ 'init', 'preload', 'create', 'update', 'render', 'shutdown', 'destroy' ]; for (var i = 0; i < defaults.length; i++) { var sceneCallback = GetValue(sceneConfig, defaults[i], null); + // Must always have an update function, no matter what (the rest are optional) + if (defaults[i] === 'update' && !sceneCallback) + { + sceneCallback = NOOP; + } + if (sceneCallback) { newScene[defaults[i]] = sceneCallback; } } - // Now let's move across any other functions or properties that may exist + // Now let's move across any other functions or properties that may exist in the extend object: /* scene: { @@ -487,10 +460,7 @@ var SceneManager = new Class({ { for (var propertyKey in sceneConfig.extend) { - if (defaults.indexOf(propertyKey) === -1) - { - newScene[propertyKey] = sceneConfig.extend[propertyKey]; - } + newScene[propertyKey] = sceneConfig.extend[propertyKey]; } } From faf89ea78a0d18e38c9aca93b4fa83a637310b3a Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 16:29:55 +0000 Subject: [PATCH 105/115] getTextureKeys method added to return all loaded textures. --- src/textures/TextureManager.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/textures/TextureManager.js b/src/textures/TextureManager.js index 8c4e158b7..8971249fa 100644 --- a/src/textures/TextureManager.js +++ b/src/textures/TextureManager.js @@ -323,6 +323,21 @@ var TextureManager = new Class({ } }, + getTextureKeys: function () + { + var output = []; + + for (var key in this.list) + { + if (key !== '__DEFAULT' && key !== '__MISSING') + { + output.push(key); + } + } + + return output; + }, + getPixel: function (x, y, key, frame) { var textureFrame = this.getFrame(key, frame); From 7e0b04df70d2e4533d13372f00a40c5a2d8c1f42 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 16:56:41 +0000 Subject: [PATCH 106/115] You can now specify Loader settings (baseURL, path, xhr settings, etc) in either the Game Config, the Scene Config or a File Config. Game config is used as the defaults. Scene config overrides those, and a File config overrides the Scene config. This fixes #3168. --- src/boot/Config.js | 12 ++++++++++++ src/loader/File.js | 3 +-- src/loader/LoaderPlugin.js | 29 +++++++++++++++++------------ src/scene/Settings.js | 4 ++++ 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/boot/Config.js b/src/boot/Config.js index 75f4dfd72..ec4369eb8 100644 --- a/src/boot/Config.js +++ b/src/boot/Config.js @@ -182,6 +182,18 @@ var Config = new Class({ this.physics = GetValue(config, 'physics', {}); this.defaultPhysicsSystem = GetValue(this.physics, 'default', false); + // Loader Defaults + this.loaderBaseURL = GetValue(config, 'loader.baseURL', ''); + this.loaderPath = GetValue(config, 'loader.path', ''); + this.loaderEnableParallel = GetValue(config, 'loader.enableParallel', true); + this.loaderMaxParallelDownloads = GetValue(config, 'loader.maxParallelDownloads', 4); + this.loaderCrossOrigin = GetValue(config, 'loader.crossOrigin', undefined); + this.loaderResponseType = GetValue(config, 'loader.responseType', ''); + this.loaderAsync = GetValue(config, 'loader.async', true); + this.loaderUser = GetValue(config, 'loader.user', ''); + this.loaderPassword = GetValue(config, 'loader.password', ''); + this.loaderTimeout = GetValue(config, 'loader.timeout', 0); + // Scene Plugins this.defaultPlugins = GetValue(config, 'plugins', DefaultScenePlugins); diff --git a/src/loader/File.js b/src/loader/File.js index 29444193f..8891979c7 100644 --- a/src/loader/File.js +++ b/src/loader/File.js @@ -81,8 +81,7 @@ var File = new Class({ this.xhrLoader.onprogress = undefined; }, - // Called when the Image loads - // ProgressEvent + // Called when the file loads, is sent a DOM ProgressEvent onLoad: function (event) { this.resetXHR(); diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index 9e12009d8..77affd239 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -3,6 +3,7 @@ var CONST = require('./const'); var CustomSet = require('../structs/Set'); var EventEmitter = require('eventemitter3'); var FileTypesManager = require('./FileTypesManager'); +var GetFastValue = require('../utils/object/GetFastValue'); var ParseXMLBitmapFont = require('../gameobjects/bitmaptext/ParseXMLBitmapFont'); var PluginManager = require('../plugins/PluginManager'); var XHRSettings = require('./XHRSettings'); @@ -33,17 +34,25 @@ var LoaderPlugin = new Class({ // Inject the available filetypes into the Loader FileTypesManager.install(this); - this.baseURL = ''; - this.path = ''; + var sceneConfig = this.systems.settings.loader; + var gameConfig = this.systems.game.config; - // Read from Game / Scene Config - this.enableParallel = true; - this.maxParallelDownloads = 4; + this.baseURL = GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL); + this.path = GetFastValue(sceneConfig, 'path', gameConfig.loaderPath); + + this.enableParallel = GetFastValue(sceneConfig, 'enableParallel', gameConfig.loaderEnableParallel); + this.maxParallelDownloads = GetFastValue(sceneConfig, 'maxParallelDownloads', gameConfig.loaderMaxParallelDownloads); // xhr specific global settings (can be overridden on a per-file basis) - this.xhr = XHRSettings(); + this.xhr = XHRSettings( + GetFastValue(sceneConfig, 'responseType', gameConfig.loaderResponseType), + GetFastValue(sceneConfig, 'async', gameConfig.loaderAsync), + GetFastValue(sceneConfig, 'user', gameConfig.loaderUser), + GetFastValue(sceneConfig, 'password', gameConfig.loaderPassword), + GetFastValue(sceneConfig, 'timeout', gameConfig.loaderTimeout) + ); - this.crossOrigin = undefined; + this.crossOrigin = GetFastValue(sceneConfig, 'crossOrigin', gameConfig.loaderCrossOrigin); this.totalToLoad = 0; this.progress = 0; @@ -59,10 +68,6 @@ var LoaderPlugin = new Class({ boot: function () { - // Set values from scene / game configs - - - var eventEmitter = this.systems.events; eventEmitter.on('shutdown', this.shutdown, this); @@ -193,7 +198,7 @@ var LoaderPlugin = new Class({ file.crossOrigin = this.crossOrigin; } - file.load(this.nextFile.bind(this), this.baseURL); + file.load(this.nextFile.bind(this), this.baseURL, this.xhr); }, nextFile: function (previousFile, success) diff --git a/src/scene/Settings.js b/src/scene/Settings.js index 0d86961ab..0b11f7268 100644 --- a/src/scene/Settings.js +++ b/src/scene/Settings.js @@ -47,6 +47,10 @@ var Settings = { physics: GetValue(config, 'physics', {}), + // Loader + + loader: GetValue(config, 'loader', {}), + // Plugins plugins: GetValue(config, 'plugins', false), From 7c7336dd305167d9cf2180d27cd90ca2e9ef8bf4 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 17:07:38 +0000 Subject: [PATCH 107/115] Loader.reset gets path and baseURL again. --- src/loader/LoaderPlugin.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index 77affd239..89dcd268a 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -34,11 +34,14 @@ var LoaderPlugin = new Class({ // Inject the available filetypes into the Loader FileTypesManager.install(this); - var sceneConfig = this.systems.settings.loader; var gameConfig = this.systems.game.config; + var sceneConfig = this.systems.settings.loader; + + this.path = ''; + this.baseURL = ''; this.baseURL = GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL); - this.path = GetFastValue(sceneConfig, 'path', gameConfig.loaderPath); + this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath)); this.enableParallel = GetFastValue(sceneConfig, 'enableParallel', gameConfig.loaderEnableParallel); this.maxParallelDownloads = GetFastValue(sceneConfig, 'maxParallelDownloads', gameConfig.loaderMaxParallelDownloads); @@ -547,9 +550,11 @@ var LoaderPlugin = new Class({ this.removeAllListeners('loaderror'); this.removeAllListeners('complete'); - this.tag = ''; - this.path = ''; - this.baseURL = ''; + var gameConfig = this.systems.game.config; + var sceneConfig = this.systems.settings.loader; + + this.baseURL = GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL); + this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath)); this.state = CONST.LOADER_IDLE; }, From 8c3422f2b48f520984021a50a2e44003c5b4be85 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 17:10:23 +0000 Subject: [PATCH 108/115] BaseURL adds trailing slash if missing. --- src/loader/LoaderPlugin.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index 89dcd268a..c3ed36b4e 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -40,7 +40,7 @@ var LoaderPlugin = new Class({ this.path = ''; this.baseURL = ''; - this.baseURL = GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL); + this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL)); this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath)); this.enableParallel = GetFastValue(sceneConfig, 'enableParallel', gameConfig.loaderEnableParallel); @@ -79,6 +79,11 @@ var LoaderPlugin = new Class({ setBaseURL: function (url) { + if (url.substr(-1) !== '/') + { + url = url.concat('/'); + } + this.baseURL = url; return this; @@ -553,7 +558,7 @@ var LoaderPlugin = new Class({ var gameConfig = this.systems.game.config; var sceneConfig = this.systems.settings.loader; - this.baseURL = GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL); + this.setBaseURL(GetFastValue(sceneConfig, 'baseURL', gameConfig.loaderBaseURL)); this.setPath(GetFastValue(sceneConfig, 'path', gameConfig.loaderPath)); this.state = CONST.LOADER_IDLE; From f3d9f145a69a05773fb05db18d732a0e3ce11aca Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 17:28:48 +0000 Subject: [PATCH 109/115] Fixed flow error when the Loader would never complete if every single file failed. --- src/loader/LoaderPlugin.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index c3ed36b4e..6ff1a72c1 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -79,7 +79,7 @@ var LoaderPlugin = new Class({ setBaseURL: function (url) { - if (url.substr(-1) !== '/') + if (url !== '' && url.substr(-1) !== '/') { url = url.concat('/'); } @@ -91,7 +91,7 @@ var LoaderPlugin = new Class({ setPath: function (path) { - if (path.substr(-1) !== '/') + if (path !== '' && path.substr(-1) !== '/') { path = path.concat('/'); } @@ -165,6 +165,8 @@ var LoaderPlugin = new Class({ { this.progress = 1 - (this.list.size / this.totalToLoad); + // console.log(this.progress); + this.emit('progress', this.progress); }, @@ -257,11 +259,19 @@ var LoaderPlugin = new Class({ this.storage.clear(); - this.queue.each(function (file) + if (this.queue.size === 0) { - // console.log('%c Calling process on ' + file.key, 'color: #000000; background: #ffff00;'); - file.onProcess(this.processUpdate.bind(this)); - }, this); + // Everything failed, so nothing to process + this.processComplete(); + } + else + { + this.queue.each(function (file) + { + // console.log('%c Calling process on ' + file.key, 'color: #000000; background: #ffff00;'); + file.onProcess(this.processUpdate.bind(this)); + }, this); + } }, // Called automatically by the File when it has finished processing From 76c7639b20b4189b11ff49de8dad80155fc2707f Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 17:29:14 +0000 Subject: [PATCH 110/115] If a file load 404s then handle this case, as it'll return the 404 page as the response type which will then try to be parsed. --- src/loader/File.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/loader/File.js b/src/loader/File.js index 8891979c7..2c4a09220 100644 --- a/src/loader/File.js +++ b/src/loader/File.js @@ -86,7 +86,14 @@ var File = new Class({ { this.resetXHR(); - this.callback(this, true); + if (event.target && event.target.status !== 200) + { + this.callback(this, false); + } + else + { + this.callback(this, true); + } }, onError: function (event) From 7577f470ae6550cd3841c53093491d3f07785538 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 17:53:07 +0000 Subject: [PATCH 111/115] You can now pass in a JS object to the JSON Loader instead of a URL. It will use the object to populate the data with. This impacts any loader type that uses json, so atlas, tilemap, audio sprite, etc. Closes #3147. --- src/loader/File.js | 19 ++++++++++++++----- src/loader/LoaderPlugin.js | 2 +- src/loader/const.js | 3 +++ src/loader/filetypes/JSONFile.js | 10 ++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/loader/File.js b/src/loader/File.js index 2c4a09220..c3754b797 100644 --- a/src/loader/File.js +++ b/src/loader/File.js @@ -154,15 +154,24 @@ var File = new Class({ this.callback = callback; - this.src = GetURL(this, baseURL); - - if (this.src.indexOf('data:') === 0) + if (this.state === CONST.FILE_POPULATED) { - console.log('Local data URI'); + this.onComplete(); + + callback(this); } else { - this.xhrLoader = XHRLoader(this, globalXHR); + this.src = GetURL(this, baseURL); + + if (this.src.indexOf('data:') === 0) + { + console.log('Local data URI'); + } + else + { + this.xhrLoader = XHRLoader(this, globalXHR); + } } } diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index 6ff1a72c1..643cf3c04 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -178,7 +178,7 @@ var LoaderPlugin = new Class({ this.list.each(function (file) { - if (file.state === CONST.FILE_PENDING && this.inflight.size < this.maxParallelDownloads) + if (file.state === CONST.FILE_POPULATED || (file.state === CONST.FILE_PENDING && this.inflight.size < this.maxParallelDownloads)) { this.inflight.set(file); diff --git a/src/loader/const.js b/src/loader/const.js index d609e5136..d8261f895 100644 --- a/src/loader/const.js +++ b/src/loader/const.js @@ -34,6 +34,9 @@ var FILE_CONST = { // File has been destroyed FILE_DESTROYED: 18, + // File was populated from local data and doesn't need an HTTP request + FILE_POPULATED: 19, + TEXTURE_ATLAS_JSON_ARRAY: 20, TEXTURE_ATLAS_JSON_HASH: 21 diff --git a/src/loader/filetypes/JSONFile.js b/src/loader/filetypes/JSONFile.js index 9d8bb0905..cd5317170 100644 --- a/src/loader/filetypes/JSONFile.js +++ b/src/loader/filetypes/JSONFile.js @@ -12,6 +12,8 @@ var JSONFile = new Class({ initialize: + // url can either be a string, in which case it is treated like a proper url, or an object, in which case it is treated as a ready-made JS Object + function JSONFile (key, url, path, xhrSettings) { var fileKey = (typeof key === 'string') ? key : GetFastValue(key, 'key', ''); @@ -27,6 +29,14 @@ var JSONFile = new Class({ }; File.call(this, fileConfig); + + if (typeof fileConfig.url === 'object') + { + // Object provided instead of a URL, so no need to actually load it (populate data with value) + this.data = fileConfig.url; + + this.state = CONST.FILE_POPULATED; + } }, onProcess: function (callback) From 4473af243ba7bae4dd14bbe110e5f65fd877a0f9 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 18:23:25 +0000 Subject: [PATCH 112/115] Frames can now have `customData` stored in them, as well as the Textures. This is populated by all of the atlas data by default and can be added to, either in the JJSON source files or at run-time. Closes #3165. --- src/textures/Frame.js | 13 +++++++++++++ src/textures/Texture.js | 3 +++ src/textures/parsers/JSONArray.js | 24 ++++++++++++++++++++++++ src/textures/parsers/JSONHash.js | 24 ++++++++++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/src/textures/Frame.js b/src/textures/Frame.js index 62eabf834..618bea543 100644 --- a/src/textures/Frame.js +++ b/src/textures/Frame.js @@ -80,6 +80,16 @@ var Frame = new Class({ */ this.centerY = Math.floor(height / 2); + /** + * @property {number} pivotX - The horizontal pivot point of this Frame. + */ + this.pivotX = 0; + + /** + * @property {number} height - The vertical pivot point of this Frame. + */ + this.pivotY = 0; + /** * Is this frame is rotated or not in the Texture? * Rotation allows you to use rotated frames in texture atlas packing. @@ -93,6 +103,9 @@ var Frame = new Class({ // Over-rides the Renderer setting? -1 = use Renderer Setting, 0 = No rounding, 1 = Round this.autoRound = -1; + // Any Frame specific custom data can be stored here + this.customData = {}; + /** * The un-modified source frame, trim and UV data. * diff --git a/src/textures/Texture.js b/src/textures/Texture.js index 8574e492e..4610afbea 100644 --- a/src/textures/Texture.js +++ b/src/textures/Texture.js @@ -36,6 +36,9 @@ var Texture = new Class({ this.frames = {}; + // Any additional data that was set in the source JSON (if any), or any extra data you'd like to store relating to this texture + this.customData = {}; + this.firstFrame = '__BASE'; this.frameTotal = 0; diff --git a/src/textures/parsers/JSONArray.js b/src/textures/parsers/JSONArray.js index 3f5389683..e5e6cf972 100644 --- a/src/textures/parsers/JSONArray.js +++ b/src/textures/parsers/JSONArray.js @@ -1,3 +1,5 @@ +var Clone = require('../../utils/object/Clone'); + var JSONArray = function (texture, sourceIndex, json) { // Malformed? @@ -9,6 +11,7 @@ var JSONArray = function (texture, sourceIndex, json) // Add in a __BASE entry (for the entire atlas) var source = texture.source[sourceIndex]; + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); // By this stage frames is a fully parsed array @@ -40,6 +43,27 @@ var JSONArray = function (texture, sourceIndex, json) newFrame.rotated = true; newFrame.updateUVsInverted(); } + + // Copy over any extra data + newFrame.customData = Clone(src); + } + + // Copy over any additional data that was in the JSON to Texture.customData + for (var dataKey in json) + { + if (dataKey === 'frames') + { + continue; + } + + if (Array.isArray(json[dataKey])) + { + texture.customData[dataKey] = json[dataKey].slice(0); + } + else + { + texture.customData[dataKey] = json[dataKey]; + } } return texture; diff --git a/src/textures/parsers/JSONHash.js b/src/textures/parsers/JSONHash.js index 498bce22e..9eb9aaad5 100644 --- a/src/textures/parsers/JSONHash.js +++ b/src/textures/parsers/JSONHash.js @@ -1,3 +1,5 @@ +var Clone = require('../../utils/object/Clone'); + var JSONHash = function (texture, sourceIndex, json) { // Malformed? @@ -9,6 +11,7 @@ var JSONHash = function (texture, sourceIndex, json) // Add in a __BASE entry (for the entire atlas) var source = texture.source[sourceIndex]; + texture.add('__BASE', sourceIndex, 0, 0, source.width, source.height); // By this stage frames is a fully parsed Object @@ -40,6 +43,27 @@ var JSONHash = function (texture, sourceIndex, json) newFrame.rotated = true; newFrame.updateUVsInverted(); } + + // Copy over any extra data + newFrame.customData = Clone(src); + } + + // Copy over any additional data that was in the JSON to Texture.customData + for (var dataKey in json) + { + if (dataKey === 'frames') + { + continue; + } + + if (Array.isArray(json[dataKey])) + { + texture.customData[dataKey] = json[dataKey].slice(0); + } + else + { + texture.customData[dataKey] = json[dataKey]; + } } return texture; From 1d22f5a59a73ecac59933f0d7d78e7f520a4c9cd Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 19:13:02 +0000 Subject: [PATCH 113/115] File has a reference to its Loader, will also now emit progress events on itself. --- src/loader/File.js | 74 ++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/src/loader/File.js b/src/loader/File.js index c3754b797..c7a4ecce8 100644 --- a/src/loader/File.js +++ b/src/loader/File.js @@ -48,6 +48,9 @@ var File = new Class({ this.xhrSettings = MergeXHRSettings(this.xhrSettings, GetFastValue(fileConfig, 'xhrSettings', {})); } + // The LoaderPlugin instance that is loading this file + this.loader = null; + this.xhrLoader = null; this.state = CONST.FILE_PENDING; @@ -70,8 +73,6 @@ var File = new Class({ // Multipart file? (i.e. an atlas and its json together) this.linkFile = undefined; this.linkType = ''; - - this.callback = null; }, resetXHR: function () @@ -81,6 +82,33 @@ var File = new Class({ this.xhrLoader.onprogress = undefined; }, + // Called by the Loader, starts the actual file downloading. + // During the load the methods onLoad, onProgress, etc are called based on the XHR events. + load: function (loader) + { + this.loader = loader; + + if (this.state === CONST.FILE_POPULATED) + { + this.onComplete(); + + loader.nextFile(this); + } + else + { + this.src = GetURL(this, loader.baseURL); + + if (this.src.indexOf('data:') === 0) + { + console.log('Local data URI'); + } + else + { + this.xhrLoader = XHRLoader(this, loader.xhr); + } + } + }, + // Called when the file loads, is sent a DOM ProgressEvent onLoad: function (event) { @@ -88,19 +116,20 @@ var File = new Class({ if (event.target && event.target.status !== 200) { - this.callback(this, false); + this.loader.nextFile(this, false); } else { - this.callback(this, true); + this.loader.nextFile(this, true); } }, + // Called when the file errors, is sent a DOM ProgressEvent onError: function (event) { this.resetXHR(); - this.callback(this, false); + this.loader.nextFile(this, false); }, onProgress: function (event) @@ -111,11 +140,14 @@ var File = new Class({ this.bytesTotal = event.total; this.percentComplete = Math.min((this.bytesLoaded / this.bytesTotal), 1); - } - // console.log(this.percentComplete + '% (' + this.bytesLoaded + ' bytes)'); + // console.log(this.percentComplete + '% (' + this.bytesLoaded + ' bytes)'); + this.loader.emit('fileprogress', this, this.percentComplete); + } }, + // Usually overriden by the FileTypes and is called by Loader.finishedLoading. + // The callback is Loader.processUpdate onProcess: function (callback) { this.state = CONST.FILE_PROCESSING; @@ -145,34 +177,6 @@ var File = new Class({ { this.state = CONST.FILE_COMPLETE; } - }, - - // Called by the Loader, starts the actual file downloading - load: function (callback, baseURL, globalXHR) - { - if (baseURL === undefined) { baseURL = ''; } - - this.callback = callback; - - if (this.state === CONST.FILE_POPULATED) - { - this.onComplete(); - - callback(this); - } - else - { - this.src = GetURL(this, baseURL); - - if (this.src.indexOf('data:') === 0) - { - console.log('Local data URI'); - } - else - { - this.xhrLoader = XHRLoader(this, globalXHR); - } - } } }); From 2f1ee57505f10b6123a6bd16a80dcff95f654879 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 19:13:11 +0000 Subject: [PATCH 114/115] Fixed event handler. --- src/scene/SceneManager.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/scene/SceneManager.js b/src/scene/SceneManager.js index 47ba18bfd..3508f48e0 100644 --- a/src/scene/SceneManager.js +++ b/src/scene/SceneManager.js @@ -777,11 +777,9 @@ var SceneManager = new Class({ * * @param {object} event - [description] */ - payloadComplete: function (event) + payloadComplete: function (loader) { - var scene = event.loader.scene; - - this.bootScene(scene); + this.bootScene(loader.scene); }, /** From 864fa638afea71dcf4a99ab236bb358cb50c116a Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Fri, 19 Jan 2018 19:13:27 +0000 Subject: [PATCH 115/115] Added LoadArray back in and sorted out callback passing. --- src/loader/LoaderPlugin.js | 51 +++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/loader/LoaderPlugin.js b/src/loader/LoaderPlugin.js index 643cf3c04..917ae1757 100644 --- a/src/loader/LoaderPlugin.js +++ b/src/loader/LoaderPlugin.js @@ -208,7 +208,7 @@ var LoaderPlugin = new Class({ file.crossOrigin = this.crossOrigin; } - file.load(this.nextFile.bind(this), this.baseURL, this.xhr); + file.load(this); }, nextFile: function (previousFile, success) @@ -574,6 +574,55 @@ var LoaderPlugin = new Class({ this.state = CONST.LOADER_IDLE; }, + loadArray: function (files) + { + if (Array.isArray(files)) + { + for (var i = 0; i < files.length; i++) + { + this.file(files[i]); + } + } + + return (this.list.size > 0); + }, + + file: function (file) + { + var entry; + var key = file.key; + + switch (file.type) + { + case 'spritesheet': + entry = this.spritesheet(key, file.url, file.config, file.xhrSettings); + break; + + case 'atlas': + entry = this.atlas(key, file.textureURL, file.atlasURL, file.textureXhrSettings, file.atlasXhrSettings); + break; + + case 'bitmapFont': + entry = this.bitmapFont(key, file.textureURL, file.xmlURL, file.textureXhrSettings, file.xmlXhrSettings); + break; + + case 'multiatlas': + entry = this.multiatlas(key, file.textureURLs, file.atlasURLs, file.textureXhrSettings, file.atlasXhrSettings); + break; + + case 'audioSprite': + entry = this.audioSprite(key, file.urls, file.json, file.config, file.audioXhrSettings, file.jsonXhrSettings); + break; + + // image, json, xml, binary, text, glsl, svg, obj + default: + entry = this[file.type](key, file.url, file.xhrSettings); + break; + } + + return entry; + }, + shutdown: function () { this.reset();