David Catuhe 6 years ago
parent
commit
07f41df750

File diff suppressed because it is too large
+ 6588 - 6559
Playground/babylon.d.txt


File diff suppressed because it is too large
+ 3399 - 3374
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.js


+ 73 - 13
dist/preview release/babylon.max.js

@@ -2302,6 +2302,9 @@ var BABYLON;
                         }
                     };
                     request.addEventListener("readystatechange", onReadyStateChange);
+                    if (Tools.UseCustomRequestHeaders) {
+                        Tools.InjectCustomRequestHeaders(request);
+                    }
                     request.send();
                 };
                 retryLoop(0);
@@ -3096,6 +3099,18 @@ var BABYLON;
                 console.timeEnd(counterName);
             }
         };
+        /**
+         * Injects the @see CustomRequestHeaders into the given request
+         * @param request the request that should be used for injection
+         */
+        Tools.InjectCustomRequestHeaders = function (request) {
+            for (var key in Tools.CustomRequestHeaders) {
+                var val = Tools.CustomRequestHeaders[key];
+                if (val) {
+                    request.setRequestHeader(key, val);
+                }
+            }
+        };
         Object.defineProperty(Tools, "Now", {
             /**
              * Gets either window.performance.now() if supported or Date.now() else
@@ -3215,6 +3230,18 @@ var BABYLON;
          */
         Tools.BaseUrl = "";
         /**
+         * Enable/Disable Custom HTTP Request Headers globally.
+         * default = false
+         * @see CustomRequestHeaders
+         */
+        Tools.UseCustomRequestHeaders = false;
+        /**
+         * Custom HTTP Request Headers to be sent with XMLHttpRequests
+         * i.e. when loading files, where the server/service expects an Authorization header.
+         * @see InjectCustomRequestHeaders injects them to an XMLHttpRequest
+         */
+        Tools.CustomRequestHeaders = {};
+        /**
          * Gets or sets the retry strategy to apply when an error happens while loading an asset
          */
         Tools.DefaultRetryStrategy = RetryStrategy.ExponentialBackoff();
@@ -15699,9 +15726,10 @@ var BABYLON;
          * @param fallback an internal argument in case the function must be called again, due to etc1 not having alpha capabilities
          * @param format internal format.  Default: RGB when extension is '.jpg' else RGBA.  Ignored for compressed textures
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param excludeLoaders array of texture loaders that should be excluded when picking a loader for the texture (default: empty array)
          * @returns a InternalTexture for assignment back into BABYLON.Texture
          */
-        Engine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallback, format, forcedExtension) {
+        Engine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallback, format, forcedExtension, excludeLoaders) {
             var _this = this;
             if (samplingMode === void 0) { samplingMode = Engine.TEXTURE_TRILINEAR_SAMPLINGMODE; }
             if (onLoad === void 0) { onLoad = null; }
@@ -15710,6 +15738,7 @@ var BABYLON;
             if (fallback === void 0) { fallback = null; }
             if (format === void 0) { format = null; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (excludeLoaders === void 0) { excludeLoaders = []; }
             var url = String(urlArg); // assign a new string, so that the original is still available in case of fallback
             var fromData = url.substr(0, 5) === "data:";
             var fromBlob = url.substr(0, 5) === "blob:";
@@ -15721,7 +15750,7 @@ var BABYLON;
             var loader = null;
             for (var _i = 0, _a = Engine._TextureLoaders; _i < _a.length; _i++) {
                 var availableLoader = _a[_i];
-                if (availableLoader.canLoad(extension, this._textureFormatInUse, fallback, isBase64, buffer ? true : false)) {
+                if (excludeLoaders.indexOf(availableLoader) === -1 && availableLoader.canLoad(extension, this._textureFormatInUse, fallback, isBase64, buffer ? true : false)) {
                     loader = availableLoader;
                     break;
                 }
@@ -15757,7 +15786,9 @@ var BABYLON;
                     if (fallbackUrl) {
                         // Add Back
                         customFallback = true;
-                        _this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture);
+                        excludeLoaders.push(loader);
+                        BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
+                        _this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
                     }
                 }
                 if (!customFallback) {
@@ -15775,11 +15806,16 @@ var BABYLON;
             // processing for non-image formats
             if (loader) {
                 var callback = function (data) {
-                    loader.loadData(data, texture, function (width, height, loadMipmap, isCompressed, done) {
-                        _this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, function () {
-                            done();
-                            return false;
-                        }, samplingMode);
+                    loader.loadData(data, texture, function (width, height, loadMipmap, isCompressed, done, loadFailed) {
+                        if (loadFailed) {
+                            onInternalError("TextureLoader failed to load data");
+                        }
+                        else {
+                            _this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, function () {
+                                done();
+                                return false;
+                            }, samplingMode);
+                        }
                     });
                 };
                 if (!buffer) {
@@ -16876,9 +16912,10 @@ var BABYLON;
          * @param lodScale defines the scale applied to environment texture. This manages the range of LOD level used for IBL according to the roughness
          * @param lodOffset defines the offset applied to environment texture. This manages first LOD level used for IBL according to the roughness
          * @param fallback defines texture to use while falling back when (compressed) texture file not found.
+         * @param excludeLoaders array of texture loaders that should be excluded when picking a loader for the texture (defualt: empty array)
          * @returns the cube texture as an InternalTexture
          */
-        Engine.prototype.createCubeTexture = function (rootUrl, scene, files, noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, fallback) {
+        Engine.prototype.createCubeTexture = function (rootUrl, scene, files, noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, fallback, excludeLoaders) {
             var _this = this;
             if (onLoad === void 0) { onLoad = null; }
             if (onError === void 0) { onError = null; }
@@ -16887,6 +16924,7 @@ var BABYLON;
             if (lodScale === void 0) { lodScale = 0; }
             if (lodOffset === void 0) { lodOffset = 0; }
             if (fallback === void 0) { fallback = null; }
+            if (excludeLoaders === void 0) { excludeLoaders = []; }
             var gl = this._gl;
             var texture = fallback ? fallback : new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_CUBE);
             texture.isCube = true;
@@ -16903,16 +16941,18 @@ var BABYLON;
             var loader = null;
             for (var _i = 0, _a = Engine._TextureLoaders; _i < _a.length; _i++) {
                 var availableLoader = _a[_i];
-                if (availableLoader.canLoad(extension, this._textureFormatInUse, fallback, false, false)) {
+                if (excludeLoaders.indexOf(availableLoader) === -1 && availableLoader.canLoad(extension, this._textureFormatInUse, fallback, false, false)) {
                     loader = availableLoader;
                     break;
                 }
             }
             var onInternalError = function (request, exception) {
                 if (loader) {
-                    var fallbackUrl = loader.getFallbackTextureUrl(rootUrl, _this._textureFormatInUse);
+                    var fallbackUrl = loader.getFallbackTextureUrl(texture.url, _this._textureFormatInUse);
+                    BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
                     if (fallbackUrl) {
-                        _this.createCubeTexture(fallbackUrl, scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture);
+                        excludeLoaders.push(loader);
+                        _this.createCubeTexture(fallbackUrl, scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture, excludeLoaders);
                     }
                 }
                 if (onError && request) {
@@ -80316,6 +80356,9 @@ var BABYLON;
                     // It could fail when coupled with HTML5 Offline API
                     var retryManifestURL = _this._currentSceneUrl + ".manifest";
                     xhr.open("GET", retryManifestURL, true);
+                    if (BABYLON.Tools.UseCustomRequestHeaders) {
+                        BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                    }
                     xhr.send();
                 }
                 else {
@@ -80323,6 +80366,9 @@ var BABYLON;
                 }
             }, false);
             try {
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             catch (ex) {
@@ -80529,6 +80575,9 @@ var BABYLON;
                         BABYLON.Tools.Error("Error in XHR request in BABYLON.Database.");
                         image.src = url;
                     }, false);
+                    if (BABYLON.Tools.CustomRequestHeaders) {
+                        BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                    }
                     xhr.send();
                 }
                 else {
@@ -80778,6 +80827,9 @@ var BABYLON;
                     BABYLON.Tools.Error("error on XHR request.");
                     callback();
                 }, false);
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             else {
@@ -81979,6 +82031,9 @@ var BABYLON;
                 noConfigFile();
             }, false);
             try {
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             catch (ex) {
@@ -101092,12 +101147,17 @@ var BABYLON;
         /** contents of the KTX container file */
         arrayBuffer, facesExpected, threeDExpected, textureArrayExpected) {
             this.arrayBuffer = arrayBuffer;
+            /**
+             * If the container has been made invalid (eg. constructor failed to correctly load array buffer)
+             */
+            this.isInvalid = false;
             // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:
             // '�', 'K', 'T', 'X', ' ', '1', '1', '�', '\r', '\n', '\x1A', '\n'
             // 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
             var identifier = new Uint8Array(this.arrayBuffer, 0, 12);
             if (identifier[0] !== 0xAB || identifier[1] !== 0x4B || identifier[2] !== 0x54 || identifier[3] !== 0x58 || identifier[4] !== 0x20 || identifier[5] !== 0x31 ||
                 identifier[6] !== 0x31 || identifier[7] !== 0xBB || identifier[8] !== 0x0D || identifier[9] !== 0x0A || identifier[10] !== 0x1A || identifier[11] !== 0x0A) {
+                this.isInvalid = true;
                 BABYLON.Tools.Error("texture missing KTX identifier");
                 return;
             }
@@ -101284,7 +101344,7 @@ var BABYLON;
             var ktx = new BABYLON.KhronosTextureContainer(data, 1);
             callback(ktx.pixelWidth, ktx.pixelHeight, false, true, function () {
                 ktx.uploadLevels(texture, texture.generateMipMaps);
-            });
+            }, ktx.isInvalid);
         };
         return KTXTextureLoader;
     }());

+ 73 - 13
dist/preview release/babylon.no-module.max.js

@@ -2269,6 +2269,9 @@ var BABYLON;
                         }
                     };
                     request.addEventListener("readystatechange", onReadyStateChange);
+                    if (Tools.UseCustomRequestHeaders) {
+                        Tools.InjectCustomRequestHeaders(request);
+                    }
                     request.send();
                 };
                 retryLoop(0);
@@ -3063,6 +3066,18 @@ var BABYLON;
                 console.timeEnd(counterName);
             }
         };
+        /**
+         * Injects the @see CustomRequestHeaders into the given request
+         * @param request the request that should be used for injection
+         */
+        Tools.InjectCustomRequestHeaders = function (request) {
+            for (var key in Tools.CustomRequestHeaders) {
+                var val = Tools.CustomRequestHeaders[key];
+                if (val) {
+                    request.setRequestHeader(key, val);
+                }
+            }
+        };
         Object.defineProperty(Tools, "Now", {
             /**
              * Gets either window.performance.now() if supported or Date.now() else
@@ -3182,6 +3197,18 @@ var BABYLON;
          */
         Tools.BaseUrl = "";
         /**
+         * Enable/Disable Custom HTTP Request Headers globally.
+         * default = false
+         * @see CustomRequestHeaders
+         */
+        Tools.UseCustomRequestHeaders = false;
+        /**
+         * Custom HTTP Request Headers to be sent with XMLHttpRequests
+         * i.e. when loading files, where the server/service expects an Authorization header.
+         * @see InjectCustomRequestHeaders injects them to an XMLHttpRequest
+         */
+        Tools.CustomRequestHeaders = {};
+        /**
          * Gets or sets the retry strategy to apply when an error happens while loading an asset
          */
         Tools.DefaultRetryStrategy = RetryStrategy.ExponentialBackoff();
@@ -15666,9 +15693,10 @@ var BABYLON;
          * @param fallback an internal argument in case the function must be called again, due to etc1 not having alpha capabilities
          * @param format internal format.  Default: RGB when extension is '.jpg' else RGBA.  Ignored for compressed textures
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param excludeLoaders array of texture loaders that should be excluded when picking a loader for the texture (default: empty array)
          * @returns a InternalTexture for assignment back into BABYLON.Texture
          */
-        Engine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallback, format, forcedExtension) {
+        Engine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallback, format, forcedExtension, excludeLoaders) {
             var _this = this;
             if (samplingMode === void 0) { samplingMode = Engine.TEXTURE_TRILINEAR_SAMPLINGMODE; }
             if (onLoad === void 0) { onLoad = null; }
@@ -15677,6 +15705,7 @@ var BABYLON;
             if (fallback === void 0) { fallback = null; }
             if (format === void 0) { format = null; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (excludeLoaders === void 0) { excludeLoaders = []; }
             var url = String(urlArg); // assign a new string, so that the original is still available in case of fallback
             var fromData = url.substr(0, 5) === "data:";
             var fromBlob = url.substr(0, 5) === "blob:";
@@ -15688,7 +15717,7 @@ var BABYLON;
             var loader = null;
             for (var _i = 0, _a = Engine._TextureLoaders; _i < _a.length; _i++) {
                 var availableLoader = _a[_i];
-                if (availableLoader.canLoad(extension, this._textureFormatInUse, fallback, isBase64, buffer ? true : false)) {
+                if (excludeLoaders.indexOf(availableLoader) === -1 && availableLoader.canLoad(extension, this._textureFormatInUse, fallback, isBase64, buffer ? true : false)) {
                     loader = availableLoader;
                     break;
                 }
@@ -15724,7 +15753,9 @@ var BABYLON;
                     if (fallbackUrl) {
                         // Add Back
                         customFallback = true;
-                        _this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture);
+                        excludeLoaders.push(loader);
+                        BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
+                        _this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
                     }
                 }
                 if (!customFallback) {
@@ -15742,11 +15773,16 @@ var BABYLON;
             // processing for non-image formats
             if (loader) {
                 var callback = function (data) {
-                    loader.loadData(data, texture, function (width, height, loadMipmap, isCompressed, done) {
-                        _this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, function () {
-                            done();
-                            return false;
-                        }, samplingMode);
+                    loader.loadData(data, texture, function (width, height, loadMipmap, isCompressed, done, loadFailed) {
+                        if (loadFailed) {
+                            onInternalError("TextureLoader failed to load data");
+                        }
+                        else {
+                            _this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, function () {
+                                done();
+                                return false;
+                            }, samplingMode);
+                        }
                     });
                 };
                 if (!buffer) {
@@ -16843,9 +16879,10 @@ var BABYLON;
          * @param lodScale defines the scale applied to environment texture. This manages the range of LOD level used for IBL according to the roughness
          * @param lodOffset defines the offset applied to environment texture. This manages first LOD level used for IBL according to the roughness
          * @param fallback defines texture to use while falling back when (compressed) texture file not found.
+         * @param excludeLoaders array of texture loaders that should be excluded when picking a loader for the texture (defualt: empty array)
          * @returns the cube texture as an InternalTexture
          */
-        Engine.prototype.createCubeTexture = function (rootUrl, scene, files, noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, fallback) {
+        Engine.prototype.createCubeTexture = function (rootUrl, scene, files, noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, fallback, excludeLoaders) {
             var _this = this;
             if (onLoad === void 0) { onLoad = null; }
             if (onError === void 0) { onError = null; }
@@ -16854,6 +16891,7 @@ var BABYLON;
             if (lodScale === void 0) { lodScale = 0; }
             if (lodOffset === void 0) { lodOffset = 0; }
             if (fallback === void 0) { fallback = null; }
+            if (excludeLoaders === void 0) { excludeLoaders = []; }
             var gl = this._gl;
             var texture = fallback ? fallback : new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_CUBE);
             texture.isCube = true;
@@ -16870,16 +16908,18 @@ var BABYLON;
             var loader = null;
             for (var _i = 0, _a = Engine._TextureLoaders; _i < _a.length; _i++) {
                 var availableLoader = _a[_i];
-                if (availableLoader.canLoad(extension, this._textureFormatInUse, fallback, false, false)) {
+                if (excludeLoaders.indexOf(availableLoader) === -1 && availableLoader.canLoad(extension, this._textureFormatInUse, fallback, false, false)) {
                     loader = availableLoader;
                     break;
                 }
             }
             var onInternalError = function (request, exception) {
                 if (loader) {
-                    var fallbackUrl = loader.getFallbackTextureUrl(rootUrl, _this._textureFormatInUse);
+                    var fallbackUrl = loader.getFallbackTextureUrl(texture.url, _this._textureFormatInUse);
+                    BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
                     if (fallbackUrl) {
-                        _this.createCubeTexture(fallbackUrl, scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture);
+                        excludeLoaders.push(loader);
+                        _this.createCubeTexture(fallbackUrl, scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture, excludeLoaders);
                     }
                 }
                 if (onError && request) {
@@ -80283,6 +80323,9 @@ var BABYLON;
                     // It could fail when coupled with HTML5 Offline API
                     var retryManifestURL = _this._currentSceneUrl + ".manifest";
                     xhr.open("GET", retryManifestURL, true);
+                    if (BABYLON.Tools.UseCustomRequestHeaders) {
+                        BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                    }
                     xhr.send();
                 }
                 else {
@@ -80290,6 +80333,9 @@ var BABYLON;
                 }
             }, false);
             try {
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             catch (ex) {
@@ -80496,6 +80542,9 @@ var BABYLON;
                         BABYLON.Tools.Error("Error in XHR request in BABYLON.Database.");
                         image.src = url;
                     }, false);
+                    if (BABYLON.Tools.CustomRequestHeaders) {
+                        BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                    }
                     xhr.send();
                 }
                 else {
@@ -80745,6 +80794,9 @@ var BABYLON;
                     BABYLON.Tools.Error("error on XHR request.");
                     callback();
                 }, false);
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             else {
@@ -81946,6 +81998,9 @@ var BABYLON;
                 noConfigFile();
             }, false);
             try {
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             catch (ex) {
@@ -101059,12 +101114,17 @@ var BABYLON;
         /** contents of the KTX container file */
         arrayBuffer, facesExpected, threeDExpected, textureArrayExpected) {
             this.arrayBuffer = arrayBuffer;
+            /**
+             * If the container has been made invalid (eg. constructor failed to correctly load array buffer)
+             */
+            this.isInvalid = false;
             // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:
             // '�', 'K', 'T', 'X', ' ', '1', '1', '�', '\r', '\n', '\x1A', '\n'
             // 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
             var identifier = new Uint8Array(this.arrayBuffer, 0, 12);
             if (identifier[0] !== 0xAB || identifier[1] !== 0x4B || identifier[2] !== 0x54 || identifier[3] !== 0x58 || identifier[4] !== 0x20 || identifier[5] !== 0x31 ||
                 identifier[6] !== 0x31 || identifier[7] !== 0xBB || identifier[8] !== 0x0D || identifier[9] !== 0x0A || identifier[10] !== 0x1A || identifier[11] !== 0x0A) {
+                this.isInvalid = true;
                 BABYLON.Tools.Error("texture missing KTX identifier");
                 return;
             }
@@ -101251,7 +101311,7 @@ var BABYLON;
             var ktx = new BABYLON.KhronosTextureContainer(data, 1);
             callback(ktx.pixelWidth, ktx.pixelHeight, false, true, function () {
                 ktx.uploadLevels(texture, texture.generateMipMaps);
-            });
+            }, ktx.isInvalid);
         };
         return KTXTextureLoader;
     }());

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/babylon.worker.js


+ 73 - 13
dist/preview release/es6.js

@@ -2269,6 +2269,9 @@ var BABYLON;
                         }
                     };
                     request.addEventListener("readystatechange", onReadyStateChange);
+                    if (Tools.UseCustomRequestHeaders) {
+                        Tools.InjectCustomRequestHeaders(request);
+                    }
                     request.send();
                 };
                 retryLoop(0);
@@ -3063,6 +3066,18 @@ var BABYLON;
                 console.timeEnd(counterName);
             }
         };
+        /**
+         * Injects the @see CustomRequestHeaders into the given request
+         * @param request the request that should be used for injection
+         */
+        Tools.InjectCustomRequestHeaders = function (request) {
+            for (var key in Tools.CustomRequestHeaders) {
+                var val = Tools.CustomRequestHeaders[key];
+                if (val) {
+                    request.setRequestHeader(key, val);
+                }
+            }
+        };
         Object.defineProperty(Tools, "Now", {
             /**
              * Gets either window.performance.now() if supported or Date.now() else
@@ -3182,6 +3197,18 @@ var BABYLON;
          */
         Tools.BaseUrl = "";
         /**
+         * Enable/Disable Custom HTTP Request Headers globally.
+         * default = false
+         * @see CustomRequestHeaders
+         */
+        Tools.UseCustomRequestHeaders = false;
+        /**
+         * Custom HTTP Request Headers to be sent with XMLHttpRequests
+         * i.e. when loading files, where the server/service expects an Authorization header.
+         * @see InjectCustomRequestHeaders injects them to an XMLHttpRequest
+         */
+        Tools.CustomRequestHeaders = {};
+        /**
          * Gets or sets the retry strategy to apply when an error happens while loading an asset
          */
         Tools.DefaultRetryStrategy = RetryStrategy.ExponentialBackoff();
@@ -15666,9 +15693,10 @@ var BABYLON;
          * @param fallback an internal argument in case the function must be called again, due to etc1 not having alpha capabilities
          * @param format internal format.  Default: RGB when extension is '.jpg' else RGBA.  Ignored for compressed textures
          * @param forcedExtension defines the extension to use to pick the right loader
+         * @param excludeLoaders array of texture loaders that should be excluded when picking a loader for the texture (default: empty array)
          * @returns a InternalTexture for assignment back into BABYLON.Texture
          */
-        Engine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallback, format, forcedExtension) {
+        Engine.prototype.createTexture = function (urlArg, noMipmap, invertY, scene, samplingMode, onLoad, onError, buffer, fallback, format, forcedExtension, excludeLoaders) {
             var _this = this;
             if (samplingMode === void 0) { samplingMode = Engine.TEXTURE_TRILINEAR_SAMPLINGMODE; }
             if (onLoad === void 0) { onLoad = null; }
@@ -15677,6 +15705,7 @@ var BABYLON;
             if (fallback === void 0) { fallback = null; }
             if (format === void 0) { format = null; }
             if (forcedExtension === void 0) { forcedExtension = null; }
+            if (excludeLoaders === void 0) { excludeLoaders = []; }
             var url = String(urlArg); // assign a new string, so that the original is still available in case of fallback
             var fromData = url.substr(0, 5) === "data:";
             var fromBlob = url.substr(0, 5) === "blob:";
@@ -15688,7 +15717,7 @@ var BABYLON;
             var loader = null;
             for (var _i = 0, _a = Engine._TextureLoaders; _i < _a.length; _i++) {
                 var availableLoader = _a[_i];
-                if (availableLoader.canLoad(extension, this._textureFormatInUse, fallback, isBase64, buffer ? true : false)) {
+                if (excludeLoaders.indexOf(availableLoader) === -1 && availableLoader.canLoad(extension, this._textureFormatInUse, fallback, isBase64, buffer ? true : false)) {
                     loader = availableLoader;
                     break;
                 }
@@ -15724,7 +15753,9 @@ var BABYLON;
                     if (fallbackUrl) {
                         // Add Back
                         customFallback = true;
-                        _this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture);
+                        excludeLoaders.push(loader);
+                        BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
+                        _this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
                     }
                 }
                 if (!customFallback) {
@@ -15742,11 +15773,16 @@ var BABYLON;
             // processing for non-image formats
             if (loader) {
                 var callback = function (data) {
-                    loader.loadData(data, texture, function (width, height, loadMipmap, isCompressed, done) {
-                        _this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, function () {
-                            done();
-                            return false;
-                        }, samplingMode);
+                    loader.loadData(data, texture, function (width, height, loadMipmap, isCompressed, done, loadFailed) {
+                        if (loadFailed) {
+                            onInternalError("TextureLoader failed to load data");
+                        }
+                        else {
+                            _this._prepareWebGLTexture(texture, scene, width, height, invertY, !loadMipmap, isCompressed, function () {
+                                done();
+                                return false;
+                            }, samplingMode);
+                        }
                     });
                 };
                 if (!buffer) {
@@ -16843,9 +16879,10 @@ var BABYLON;
          * @param lodScale defines the scale applied to environment texture. This manages the range of LOD level used for IBL according to the roughness
          * @param lodOffset defines the offset applied to environment texture. This manages first LOD level used for IBL according to the roughness
          * @param fallback defines texture to use while falling back when (compressed) texture file not found.
+         * @param excludeLoaders array of texture loaders that should be excluded when picking a loader for the texture (defualt: empty array)
          * @returns the cube texture as an InternalTexture
          */
-        Engine.prototype.createCubeTexture = function (rootUrl, scene, files, noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, fallback) {
+        Engine.prototype.createCubeTexture = function (rootUrl, scene, files, noMipmap, onLoad, onError, format, forcedExtension, createPolynomials, lodScale, lodOffset, fallback, excludeLoaders) {
             var _this = this;
             if (onLoad === void 0) { onLoad = null; }
             if (onError === void 0) { onError = null; }
@@ -16854,6 +16891,7 @@ var BABYLON;
             if (lodScale === void 0) { lodScale = 0; }
             if (lodOffset === void 0) { lodOffset = 0; }
             if (fallback === void 0) { fallback = null; }
+            if (excludeLoaders === void 0) { excludeLoaders = []; }
             var gl = this._gl;
             var texture = fallback ? fallback : new BABYLON.InternalTexture(this, BABYLON.InternalTexture.DATASOURCE_CUBE);
             texture.isCube = true;
@@ -16870,16 +16908,18 @@ var BABYLON;
             var loader = null;
             for (var _i = 0, _a = Engine._TextureLoaders; _i < _a.length; _i++) {
                 var availableLoader = _a[_i];
-                if (availableLoader.canLoad(extension, this._textureFormatInUse, fallback, false, false)) {
+                if (excludeLoaders.indexOf(availableLoader) === -1 && availableLoader.canLoad(extension, this._textureFormatInUse, fallback, false, false)) {
                     loader = availableLoader;
                     break;
                 }
             }
             var onInternalError = function (request, exception) {
                 if (loader) {
-                    var fallbackUrl = loader.getFallbackTextureUrl(rootUrl, _this._textureFormatInUse);
+                    var fallbackUrl = loader.getFallbackTextureUrl(texture.url, _this._textureFormatInUse);
+                    BABYLON.Tools.Warn(loader.constructor.name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
                     if (fallbackUrl) {
-                        _this.createCubeTexture(fallbackUrl, scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture);
+                        excludeLoaders.push(loader);
+                        _this.createCubeTexture(fallbackUrl, scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture, excludeLoaders);
                     }
                 }
                 if (onError && request) {
@@ -80283,6 +80323,9 @@ var BABYLON;
                     // It could fail when coupled with HTML5 Offline API
                     var retryManifestURL = _this._currentSceneUrl + ".manifest";
                     xhr.open("GET", retryManifestURL, true);
+                    if (BABYLON.Tools.UseCustomRequestHeaders) {
+                        BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                    }
                     xhr.send();
                 }
                 else {
@@ -80290,6 +80333,9 @@ var BABYLON;
                 }
             }, false);
             try {
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             catch (ex) {
@@ -80496,6 +80542,9 @@ var BABYLON;
                         BABYLON.Tools.Error("Error in XHR request in BABYLON.Database.");
                         image.src = url;
                     }, false);
+                    if (BABYLON.Tools.CustomRequestHeaders) {
+                        BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                    }
                     xhr.send();
                 }
                 else {
@@ -80745,6 +80794,9 @@ var BABYLON;
                     BABYLON.Tools.Error("error on XHR request.");
                     callback();
                 }, false);
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             else {
@@ -81946,6 +81998,9 @@ var BABYLON;
                 noConfigFile();
             }, false);
             try {
+                if (BABYLON.Tools.UseCustomRequestHeaders) {
+                    BABYLON.Tools.InjectCustomRequestHeaders(xhr);
+                }
                 xhr.send();
             }
             catch (ex) {
@@ -101059,12 +101114,17 @@ var BABYLON;
         /** contents of the KTX container file */
         arrayBuffer, facesExpected, threeDExpected, textureArrayExpected) {
             this.arrayBuffer = arrayBuffer;
+            /**
+             * If the container has been made invalid (eg. constructor failed to correctly load array buffer)
+             */
+            this.isInvalid = false;
             // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:
             // '�', 'K', 'T', 'X', ' ', '1', '1', '�', '\r', '\n', '\x1A', '\n'
             // 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
             var identifier = new Uint8Array(this.arrayBuffer, 0, 12);
             if (identifier[0] !== 0xAB || identifier[1] !== 0x4B || identifier[2] !== 0x54 || identifier[3] !== 0x58 || identifier[4] !== 0x20 || identifier[5] !== 0x31 ||
                 identifier[6] !== 0x31 || identifier[7] !== 0xBB || identifier[8] !== 0x0D || identifier[9] !== 0x0A || identifier[10] !== 0x1A || identifier[11] !== 0x0A) {
+                this.isInvalid = true;
                 BABYLON.Tools.Error("texture missing KTX identifier");
                 return;
             }
@@ -101251,7 +101311,7 @@ var BABYLON;
             var ktx = new BABYLON.KhronosTextureContainer(data, 1);
             callback(ktx.pixelWidth, ktx.pixelHeight, false, true, function () {
                 ktx.uploadLevels(texture, texture.generateMipMaps);
-            });
+            }, ktx.isInvalid);
         };
         return KTXTextureLoader;
     }());

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js