David Catuhe 6 tahun lalu
induk
melakukan
30ac25aa4a
32 mengubah file dengan 15968 tambahan dan 15810 penghapusan
  1. 7096 7051
      Playground/babylon.d.txt
  2. 1 1
      Tools/Gulp/config.json
  3. 2 5
      Viewer/src/viewer/viewer.ts
  4. 0 6
      Viewer/tests/commons/helper.ts
  5. 8043 7998
      dist/preview release/babylon.d.ts
  6. 1 1
      dist/preview release/babylon.js
  7. 119 113
      dist/preview release/babylon.max.js
  8. 119 113
      dist/preview release/babylon.no-module.max.js
  9. 1 1
      dist/preview release/babylon.worker.js
  10. 119 113
      dist/preview release/es6.js
  11. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  12. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  13. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js
  14. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  15. 1 1
      dist/preview release/loaders/babylonjs.loaders.js
  16. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  17. 1 1
      dist/preview release/viewer/babylon.viewer.d.ts
  18. 1 1
      dist/preview release/viewer/babylon.viewer.js
  19. 3 3
      dist/preview release/viewer/babylon.viewer.max.js
  20. 1 1
      dist/preview release/viewer/babylon.viewer.module.d.ts
  21. 4 0
      dist/preview release/what's new.md
  22. 15 15
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  23. 2 2
      src/Audio/babylon.audioEngine.ts
  24. 19 14
      src/Engine/babylon.engine.ts
  25. 5 5
      src/Loading/babylon.sceneLoader.ts
  26. 237 237
      src/Mesh/babylon.mesh.ts
  27. 5 5
      src/Mesh/babylon.meshBuilder.ts
  28. 41 0
      src/Offline/babylon.IOfflineProvider.ts
  29. 86 80
      src/Tools/babylon.database.ts
  30. 18 19
      src/Tools/babylon.tools.ts
  31. 8 7
      src/babylon.scene.ts
  32. 15 12
      tests/validation/validate.html

File diff ditekan karena terlalu besar
+ 7096 - 7051
Playground/babylon.d.txt


+ 1 - 1
Tools/Gulp/config.json

@@ -676,7 +676,7 @@
         },
         "offline": {
             "files": [
-                "../../src/Tools/babylon.database.js"
+                "../../src/Offline/babylon.database.js"
             ],
             "dependUpon": [
                 "core"

+ 2 - 5
Viewer/src/viewer/viewer.ts

@@ -1,4 +1,4 @@
-import { Database, Effect, Engine, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Observable, RenderingManager, Scene, SceneLoaderProgressEvent, TargetCamera, Tools, Vector3, Observer } from 'babylonjs';
+import { Effect, Engine, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Observable, RenderingManager, Scene, SceneLoaderProgressEvent, TargetCamera, Tools, Vector3, Observer } from 'babylonjs';
 import { IModelConfiguration, IObserversConfiguration, ViewerConfiguration } from '../configuration/';
 import { processConfigurationCompatibility } from '../configuration/configurationCompatibility';
 import { ConfigurationContainer } from '../configuration/configurationContainer';
@@ -14,7 +14,7 @@ import { TemplateManager } from '../templating/templateManager';
 import { viewerManager } from './viewerManager';
 
 /**
- * The AbstractViewr is the center of Babylon's viewer.
+ * The AbstractViewer is the center of Babylon's viewer.
  * It is the basic implementation of the default viewer and is responsible of loading and showing the model and the templates
  */
 export abstract class AbstractViewer {
@@ -649,9 +649,6 @@ export abstract class AbstractViewer {
 
         this.engine = new Engine(this.canvas, !!config.antialiasing, config.engineOptions);
 
-        // Disable manifest checking
-        Database.IDBStorageEnabled = false;
-
         if (!config.disableResize) {
             window.addEventListener('resize', this._resize);
         }

+ 0 - 6
Viewer/tests/commons/helper.ts

@@ -141,9 +141,6 @@ export class NullEngineAbstractViewer extends AbstractViewer {
 
         this.sceneManager = new SceneManager(this.engine, this.configurationContainer, this.observablesManager);
 
-        // Disable manifest checking
-        BABYLON.Database.IDBStorageEnabled = false;
-
         if (!config.disableResize) {
             window.addEventListener('resize', this._resize);
         }
@@ -183,9 +180,6 @@ export class NullEngineDefaultViewer extends DefaultViewer {
 
         this.sceneManager = new SceneManager(this.engine, this.configurationContainer, this.observablesManager);
 
-        // Disable manifest checking
-        BABYLON.Database.IDBStorageEnabled = false;
-
         if (!config.disableResize) {
             window.addEventListener('resize', this._resize);
         }

File diff ditekan karena terlalu besar
+ 8043 - 7998
dist/preview release/babylon.d.ts


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/babylon.js


+ 119 - 113
dist/preview release/babylon.max.js

@@ -2072,10 +2072,10 @@ var BABYLON;
          * @param input url string, ArrayBuffer, or Blob to load
          * @param onLoad callback called when the image successfully loads
          * @param onError callback called when the image fails to load
-         * @param database database for caching
+         * @param offlineProvider offline provider for caching
          * @returns the HTMLImageElement of the loaded image
          */
-        Tools.LoadImage = function (input, onLoad, onError, database) {
+        Tools.LoadImage = function (input, onLoad, onError, offlineProvider) {
             var url;
             var usingObjectURL = false;
             if (input instanceof ArrayBuffer) {
@@ -2113,17 +2113,16 @@ var BABYLON;
             };
             img.addEventListener("load", loadHandler);
             img.addEventListener("error", errorHandler);
-            var noIndexedDB = function () {
+            var noOfflineSupport = function () {
                 img.src = url;
             };
-            var loadFromIndexedDB = function () {
-                if (database) {
-                    database.loadImageFromDB(url, img);
+            var loadFromOfflineSupport = function () {
+                if (offlineProvider) {
+                    offlineProvider.loadImage(url, img);
                 }
             };
-            //ANY database to do!
-            if (url.substr(0, 5) !== "data:" && database && database.enableTexturesOffline && BABYLON.Database.IsUASupportingBlobStorage) {
-                database.openAsync(loadFromIndexedDB, noIndexedDB);
+            if (url.substr(0, 5) !== "data:" && offlineProvider && offlineProvider.enableTexturesOffline) {
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport);
             }
             else {
                 if (url.indexOf("file:") !== -1) {
@@ -2147,7 +2146,7 @@ var BABYLON;
                         return img;
                     }
                 }
-                noIndexedDB();
+                noOfflineSupport();
             }
             return img;
         };
@@ -2156,12 +2155,12 @@ var BABYLON;
          * @param url url string, ArrayBuffer, or Blob to load
          * @param onSuccess callback called when the file successfully loads
          * @param onProgress callback called while file is loading (if the server supports this mode)
-         * @param database  database for caching
+         * @param offlineProvider defines the offline provider for caching
          * @param useArrayBuffer defines a boolean indicating that date must be returned as ArrayBuffer
          * @param onError callback called when the file fails to load
          * @returns a file request object
          */
-        Tools.LoadFile = function (url, onSuccess, onProgress, database, useArrayBuffer, onError) {
+        Tools.LoadFile = function (url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError) {
             url = Tools.CleanUrl(url);
             url = Tools.PreprocessUrl(url);
             // If file and file input are set
@@ -2242,8 +2241,8 @@ var BABYLON;
                 retryLoop(0);
             };
             // Caching all files
-            if (database && database.enableSceneOffline) {
-                var noIndexedDB_1 = function (request) {
+            if (offlineProvider && offlineProvider.enableSceneOffline) {
+                var noOfflineSupport_1 = function (request) {
                     if (request && request.status > 400) {
                         if (onError) {
                             onError(request);
@@ -2255,13 +2254,13 @@ var BABYLON;
                         }
                     }
                 };
-                var loadFromIndexedDB = function () {
+                var loadFromOfflineSupport = function () {
                     // TODO: database needs to support aborting and should return a IFileRequest
                     if (aborted) {
                         return;
                     }
-                    if (database) {
-                        database.loadFileFromDB(url, function (data) {
+                    if (offlineProvider) {
+                        offlineProvider.loadFile(url, function (data) {
                             if (!aborted) {
                                 onSuccess(data);
                             }
@@ -2270,10 +2269,10 @@ var BABYLON;
                             if (!aborted) {
                                 onProgress(event);
                             }
-                        } : undefined, noIndexedDB_1, useArrayBuffer);
+                        } : undefined, noOfflineSupport_1, useArrayBuffer);
                     }
                 };
-                database.openAsync(loadFromIndexedDB, noIndexedDB_1);
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport_1);
             }
             else {
                 requestFile();
@@ -12291,7 +12290,7 @@ var BABYLON;
             /** @hidden */
             this._badDesktopOS = false;
             /**
-             * Gets or sets a value indicating if we want to disable texture binding optmization.
+             * Gets or sets a value indicating if we want to disable texture binding optimization.
              * This could be required on some buggy drivers which wants to have textures bound in a progressive order.
              * By default Babylon.js will try to let textures bound where they are and only update the samplers to point where the texture is
              */
@@ -12641,7 +12640,7 @@ var BABYLON;
             // Detect if we are running on a faulty buggy desktop OS.
             this._badDesktopOS = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
             console.log("Babylon.js engine (v" + Engine.Version + ") launched");
-            this.enableOfflineSupport = (BABYLON.Database !== undefined);
+            this.enableOfflineSupport = Engine.OfflineProviderFactory !== undefined;
         }
         Object.defineProperty(Engine, "LastCreatedEngine", {
             /**
@@ -15432,7 +15431,7 @@ var BABYLON;
                     onErrorCallBack(message, exception);
                 }
             };
-            img = BABYLON.Tools.LoadImage(url, onload, onerror, scene ? scene.database : null);
+            img = BABYLON.Tools.LoadImage(url, onload, onerror, scene ? scene.offlineProvider : null);
             if (scene) {
                 scene._addPendingData(img);
             }
@@ -15554,7 +15553,7 @@ var BABYLON;
                     });
                 };
                 if (!buffer) {
-                    this._loadFile(url, callback, undefined, scene ? scene.database : undefined, true, function (request, exception) {
+                    this._loadFile(url, callback, undefined, scene ? scene.offlineProvider : undefined, true, function (request, exception) {
                         onInternalError("Unable to load " + (request ? request.responseURL : url, exception));
                     });
                 }
@@ -15614,11 +15613,11 @@ var BABYLON;
                         onload(buffer);
                     }
                     else {
-                        BABYLON.Tools.LoadImage(url, onload, onInternalError, scene ? scene.database : null);
+                        BABYLON.Tools.LoadImage(url, onload, onInternalError, scene ? scene.offlineProvider : null);
                     }
                 }
                 else if (typeof buffer === "string" || buffer instanceof ArrayBuffer || buffer instanceof Blob) {
-                    BABYLON.Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.database : null);
+                    BABYLON.Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.offlineProvider : null);
                 }
                 else {
                     onload(buffer);
@@ -16963,7 +16962,7 @@ var BABYLON;
             };
             this._loadFile(url, function (data) {
                 internalCallback(data);
-            }, undefined, scene.database, true, onerror);
+            }, undefined, scene.offlineProvider, true, onerror);
             return texture;
         };
         /**
@@ -18232,9 +18231,9 @@ var BABYLON;
             return this._gl.RGBA8;
         };
         /** @hidden */
-        Engine.prototype._loadFile = function (url, onSuccess, onProgress, database, useArrayBuffer, onError) {
+        Engine.prototype._loadFile = function (url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError) {
             var _this = this;
-            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
+            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
                 _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
@@ -18242,12 +18241,12 @@ var BABYLON;
             return request;
         };
         /** @hidden */
-        Engine.prototype._loadFileAsync = function (url, database, useArrayBuffer) {
+        Engine.prototype._loadFileAsync = function (url, offlineProvider, useArrayBuffer) {
             var _this = this;
             return new Promise(function (resolve, reject) {
                 _this._loadFile(url, function (data) {
                     resolve(data);
-                }, undefined, database, useArrayBuffer, function (request, exception) {
+                }, undefined, offlineProvider, useArrayBuffer, function (request, exception) {
                     reject(exception);
                 });
             });
@@ -29934,9 +29933,9 @@ var BABYLON;
             }
         };
         /** @hidden */
-        Scene.prototype._loadFile = function (url, onSuccess, onProgress, useDatabase, useArrayBuffer, onError) {
+        Scene.prototype._loadFile = function (url, onSuccess, onProgress, useOfflineSupport, useArrayBuffer, onError) {
             var _this = this;
-            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, useDatabase ? this.database : undefined, useArrayBuffer, onError);
+            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, useOfflineSupport ? this.offlineProvider : undefined, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
                 _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
@@ -29944,12 +29943,12 @@ var BABYLON;
             return request;
         };
         /** @hidden */
-        Scene.prototype._loadFileAsync = function (url, useDatabase, useArrayBuffer) {
+        Scene.prototype._loadFileAsync = function (url, useOfflineSupport, useArrayBuffer) {
             var _this = this;
             return new Promise(function (resolve, reject) {
                 _this._loadFile(url, function (data) {
                     resolve(data);
-                }, undefined, useDatabase, useArrayBuffer, function (request, exception) {
+                }, undefined, useOfflineSupport, useArrayBuffer, function (request, exception) {
                     reject(exception);
                 });
             });
@@ -33948,7 +33947,7 @@ var BABYLON;
                 });
                 _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
                 scene._removePendingData(_this);
-            }, function () { }, scene.database, getBinaryData);
+            }, function () { }, scene.offlineProvider, getBinaryData);
             return this;
         };
         /**
@@ -34181,7 +34180,7 @@ var BABYLON;
                     onSuccess(_this);
                 }
             };
-            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
+            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.offlineProvider);
             return this;
         };
         /**
@@ -69928,7 +69927,7 @@ var BABYLON;
                 }
                 ground._setReady(true);
             };
-            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
+            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.offlineProvider);
             return ground;
         };
         /**
@@ -70652,7 +70651,7 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
-    // Sets the default audio engine to Babylon JS.
+    // Sets the default audio engine to Babylon.js
     BABYLON.Engine.AudioEngineFactory = function (hostElement) { return new AudioEngine(hostElement); };
     /**
      * This represents the default audio engine used in babylon.
@@ -77765,14 +77764,14 @@ var BABYLON;
                 plugin = registeredPlugin.plugin;
             }
             var useArrayBuffer = registeredPlugin.isBinary;
-            var database;
+            var offlineProvider;
             SceneLoader.OnPluginActivatedObservable.notifyObservers(plugin);
             var dataCallback = function (data, responseURL) {
                 if (scene.isDisposed) {
                     onError("Scene has been disposed");
                     return;
                 }
-                scene.database = database;
+                scene.offlineProvider = offlineProvider;
                 onSuccess(plugin, data, responseURL);
             };
             var request = null;
@@ -77794,7 +77793,7 @@ var BABYLON;
                 }
                 request = BABYLON.Tools.LoadFile(fileInfo.url, dataCallback, onProgress ? function (event) {
                     onProgress(SceneLoaderProgressEvent.FromProgressEvent(event));
-                } : undefined, database, useArrayBuffer, function (request, exception) {
+                } : undefined, offlineProvider, useArrayBuffer, function (request, exception) {
                     onError("Failed to load scene." + (exception ? " " + exception.message : ""), exception);
                 });
             };
@@ -77817,9 +77816,9 @@ var BABYLON;
                     }
                     canUseOfflineSupport = !exceptionFound;
                 }
-                if (canUseOfflineSupport) {
+                if (canUseOfflineSupport && BABYLON.Engine.OfflineProviderFactory) {
                     // Checking if a manifest file has been set for this scene and if offline mode has been requested
-                    database = new BABYLON.Database(fileInfo.url, manifestChecked, engine.disableManifestCheck);
+                    offlineProvider = BABYLON.Engine.OfflineProviderFactory(fileInfo.url, manifestChecked, engine.disableManifestCheck);
                 }
                 else {
                     manifestChecked();
@@ -79460,9 +79459,14 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    // Sets the default offline provider to Babylon.js
+    BABYLON.Engine.OfflineProviderFactory = function (urlToScene, callbackManifestChecked, disableManifestCheck) {
+        if (disableManifestCheck === void 0) { disableManifestCheck = false; }
+        return new Database(urlToScene, callbackManifestChecked, disableManifestCheck);
+    };
     /**
      * Class used to enable access to IndexedDB
-     * @see @https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
+     * @see http://doc.babylonjs.com/how_to/caching_resources_in_indexeddb
      */
     var Database = /** @class */ (function () {
         /**
@@ -79475,25 +79479,25 @@ var BABYLON;
             if (disableManifestCheck === void 0) { disableManifestCheck = false; }
             var _this = this;
             // Handling various flavors of prefixed version of IndexedDB
-            this.idbFactory = (window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
-            this.callbackManifestChecked = callbackManifestChecked;
-            this.currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
-            this.db = null;
+            this._idbFactory = (window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
+            this._callbackManifestChecked = callbackManifestChecked;
+            this._currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
+            this._db = null;
             this._enableSceneOffline = false;
             this._enableTexturesOffline = false;
-            this.manifestVersionFound = 0;
-            this.mustUpdateRessources = false;
-            this.hasReachedQuota = false;
+            this._manifestVersionFound = 0;
+            this._mustUpdateRessources = false;
+            this._hasReachedQuota = false;
             if (!Database.IDBStorageEnabled) {
-                this.callbackManifestChecked(true);
+                this._callbackManifestChecked(true);
             }
             else {
                 if (disableManifestCheck) {
                     this._enableSceneOffline = true;
                     this._enableTexturesOffline = true;
-                    this.manifestVersionFound = 1;
+                    this._manifestVersionFound = 1;
                     BABYLON.Tools.SetImmediate(function () {
-                        _this.callbackManifestChecked(true);
+                        _this._callbackManifestChecked(true);
                     });
                 }
                 else {
@@ -79526,10 +79530,10 @@ var BABYLON;
             var noManifestFile = function () {
                 _this._enableSceneOffline = false;
                 _this._enableTexturesOffline = false;
-                _this.callbackManifestChecked(false);
+                _this._callbackManifestChecked(false);
             };
             var timeStampUsed = false;
-            var manifestURL = this.currentSceneUrl + ".manifest";
+            var manifestURL = this._currentSceneUrl + ".manifest";
             var xhr = new XMLHttpRequest();
             if (navigator.onLine) {
                 // Adding a timestamp to by-pass browsers' cache
@@ -79542,12 +79546,12 @@ var BABYLON;
                     try {
                         var manifestFile = JSON.parse(xhr.response);
                         _this._enableSceneOffline = manifestFile.enableSceneOffline;
-                        _this._enableTexturesOffline = manifestFile.enableTexturesOffline;
+                        _this._enableTexturesOffline = manifestFile.enableTexturesOffline && Database.IsUASupportingBlobStorage;
                         if (manifestFile.version && !isNaN(parseInt(manifestFile.version))) {
-                            _this.manifestVersionFound = manifestFile.version;
+                            _this._manifestVersionFound = manifestFile.version;
                         }
-                        if (_this.callbackManifestChecked) {
-                            _this.callbackManifestChecked(true);
+                        if (_this._callbackManifestChecked) {
+                            _this._callbackManifestChecked(true);
                         }
                     }
                     catch (ex) {
@@ -79563,7 +79567,7 @@ var BABYLON;
                     timeStampUsed = false;
                     // Let's retry without the timeStamp
                     // It could fail when coupled with HTML5 Offline API
-                    var retryManifestURL = _this.currentSceneUrl + ".manifest";
+                    var retryManifestURL = _this._currentSceneUrl + ".manifest";
                     xhr.open("GET", retryManifestURL, true);
                     xhr.send();
                 }
@@ -79576,7 +79580,7 @@ var BABYLON;
             }
             catch (ex) {
                 BABYLON.Tools.Error("Error on XHR send request.");
-                this.callbackManifestChecked(false);
+                this._callbackManifestChecked(false);
             }
         };
         /**
@@ -79584,27 +79588,27 @@ var BABYLON;
          * @param successCallback defines the callback to call on success
          * @param errorCallback defines the callback to call on error
          */
-        Database.prototype.openAsync = function (successCallback, errorCallback) {
+        Database.prototype.open = function (successCallback, errorCallback) {
             var _this = this;
             var handleError = function () {
-                _this.isSupported = false;
+                _this._isSupported = false;
                 if (errorCallback) {
                     errorCallback();
                 }
             };
-            if (!this.idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
+            if (!this._idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
                 // Your browser doesn't support IndexedDB
-                this.isSupported = false;
+                this._isSupported = false;
                 if (errorCallback) {
                     errorCallback();
                 }
             }
             else {
                 // If the DB hasn't been opened or created yet
-                if (!this.db) {
-                    this.hasReachedQuota = false;
-                    this.isSupported = true;
-                    var request = this.idbFactory.open("babylonjs", 1);
+                if (!this._db) {
+                    this._hasReachedQuota = false;
+                    this._isSupported = true;
+                    var request = this._idbFactory.open("babylonjs", 1);
                     // Could occur if user is blocking the quota for the DB and/or doesn't grant access to IndexedDB
                     request.onerror = function (event) {
                         handleError();
@@ -79616,17 +79620,17 @@ var BABYLON;
                     };
                     // DB has been opened successfully
                     request.onsuccess = function (event) {
-                        _this.db = request.result;
+                        _this._db = request.result;
                         successCallback();
                     };
                     // Initialization of the DB. Creating Scenes & Textures stores
                     request.onupgradeneeded = function (event) {
-                        _this.db = (event.target).result;
-                        if (_this.db) {
+                        _this._db = (event.target).result;
+                        if (_this._db) {
                             try {
-                                _this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
-                                _this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
-                                _this.db.createObjectStore("textures", { keyPath: "textureUrl" });
+                                _this._db.createObjectStore("scenes", { keyPath: "sceneUrl" });
+                                _this._db.createObjectStore("versions", { keyPath: "sceneUrl" });
+                                _this._db.createObjectStore("textures", { keyPath: "textureUrl" });
                             }
                             catch (ex) {
                                 BABYLON.Tools.Error("Error while creating object stores. Exception: " + ex.message);
@@ -79648,11 +79652,11 @@ var BABYLON;
          * @param url defines the url to load from
          * @param image defines the target DOM image
          */
-        Database.prototype.loadImageFromDB = function (url, image) {
+        Database.prototype.loadImage = function (url, image) {
             var _this = this;
             var completeURL = Database._ReturnFullUrlLocation(url);
             var saveAndLoadImage = function () {
-                if (!_this.hasReachedQuota && _this.db !== null) {
+                if (!_this._hasReachedQuota && _this._db !== null) {
                     // the texture is not yet in the DB, let's try to save it
                     _this._saveImageIntoDBAsync(completeURL, image);
                 }
@@ -79662,7 +79666,7 @@ var BABYLON;
                     image.src = url;
                 }
             };
-            if (!this.mustUpdateRessources) {
+            if (!this._mustUpdateRessources) {
                 this._loadImageFromDBAsync(completeURL, image, saveAndLoadImage);
             }
             // First time we're download the images or update requested in the manifest file by a version change
@@ -79671,9 +79675,9 @@ var BABYLON;
             }
         };
         Database.prototype._loadImageFromDBAsync = function (url, image, notInDBCallback) {
-            if (this.isSupported && this.db !== null) {
+            if (this._isSupported && this._db !== null) {
                 var texture;
-                var transaction = this.db.transaction(["textures"]);
+                var transaction = this._db.transaction(["textures"]);
                 transaction.onabort = function (event) {
                     image.src = url;
                 };
@@ -79708,7 +79712,7 @@ var BABYLON;
         };
         Database.prototype._saveImageIntoDBAsync = function (url, image) {
             var _this = this;
-            if (this.isSupported) {
+            if (this._isSupported) {
                 // In case of error (type not supported or quota exceeded), we're at least sending back XHR data to allow texture loading later on
                 var generateBlobUrl = function () {
                     var blobTextureURL;
@@ -79731,10 +79735,10 @@ var BABYLON;
                     xhr.open("GET", url, true);
                     xhr.responseType = "blob";
                     xhr.addEventListener("load", function () {
-                        if (xhr.status === 200 && _this.db) {
+                        if (xhr.status === 200 && _this._db) {
                             // Blob as response (XHR2)
                             blob = xhr.response;
-                            var transaction = _this.db.transaction(["textures"], "readwrite");
+                            var transaction = _this._db.transaction(["textures"], "readwrite");
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = function (event) {
                                 try {
@@ -79742,7 +79746,7 @@ var BABYLON;
                                     var srcElement = (event.srcElement || event.target);
                                     var error = srcElement.error;
                                     if (error && error.name === "QuotaExceededError") {
-                                        _this.hasReachedQuota = true;
+                                        _this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -79765,6 +79769,7 @@ var BABYLON;
                                 // "DataCloneError" generated by Chrome when you try to inject blob into IndexedDB
                                 if (ex.code === 25) {
                                     Database.IsUASupportingBlobStorage = false;
+                                    _this._enableTexturesOffline = false;
                                 }
                                 image.src = url;
                             }
@@ -79798,15 +79803,15 @@ var BABYLON;
         };
         Database.prototype._loadVersionFromDBAsync = function (url, callback, updateInDBCallback) {
             var _this = this;
-            if (this.isSupported && this.db) {
+            if (this._isSupported && this._db) {
                 var version;
                 try {
-                    var transaction = this.db.transaction(["versions"]);
+                    var transaction = this._db.transaction(["versions"]);
                     transaction.oncomplete = function (event) {
                         if (version) {
                             // If the version in the JSON file is different from the version in DB
-                            if (_this.manifestVersionFound !== version.data) {
-                                _this.mustUpdateRessources = true;
+                            if (_this._manifestVersionFound !== version.data) {
+                                _this._mustUpdateRessources = true;
                                 updateInDBCallback();
                             }
                             else {
@@ -79815,7 +79820,7 @@ var BABYLON;
                         }
                         // version was not found in DB
                         else {
-                            _this.mustUpdateRessources = true;
+                            _this._mustUpdateRessources = true;
                             updateInDBCallback();
                         }
                     };
@@ -79843,25 +79848,25 @@ var BABYLON;
         };
         Database.prototype._saveVersionIntoDBAsync = function (url, callback) {
             var _this = this;
-            if (this.isSupported && !this.hasReachedQuota && this.db) {
+            if (this._isSupported && !this._hasReachedQuota && this._db) {
                 try {
                     // Open a transaction to the database
-                    var transaction = this.db.transaction(["versions"], "readwrite");
+                    var transaction = this._db.transaction(["versions"], "readwrite");
                     // the transaction could abort because of a QuotaExceededError error
                     transaction.onabort = function (event) {
                         try { //backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                             var error = event.srcElement['error'];
                             if (error && error.name === "QuotaExceededError") {
-                                _this.hasReachedQuota = true;
+                                _this._hasReachedQuota = true;
                             }
                         }
                         catch (ex) { }
                         callback(-1);
                     };
                     transaction.oncomplete = function (event) {
-                        callback(_this.manifestVersionFound);
+                        callback(_this._manifestVersionFound);
                     };
-                    var newVersion = { sceneUrl: url, data: this.manifestVersionFound };
+                    var newVersion = { sceneUrl: url, data: this._manifestVersionFound };
                     // Put the scene into the database
                     var addRequest = transaction.objectStore("versions").put(newVersion);
                     addRequest.onsuccess = function (event) {
@@ -79887,20 +79892,20 @@ var BABYLON;
          * @param errorCallback defines a callback to call on error
          * @param useArrayBuffer defines a boolean to use array buffer instead of text string
          */
-        Database.prototype.loadFileFromDB = function (url, sceneLoaded, progressCallBack, errorCallback, useArrayBuffer) {
+        Database.prototype.loadFile = function (url, sceneLoaded, progressCallBack, errorCallback, useArrayBuffer) {
             var _this = this;
             var completeUrl = Database._ReturnFullUrlLocation(url);
             var saveAndLoadFile = function () {
                 // the scene is not yet in the DB, let's try to save it
-                _this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                _this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
             };
             this._checkVersionFromDB(completeUrl, function (version) {
                 if (version !== -1) {
-                    if (!_this.mustUpdateRessources) {
-                        _this._loadFileFromDBAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
+                    if (!_this._mustUpdateRessources) {
+                        _this._loadFileAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
                     }
                     else {
-                        _this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                        _this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
                     }
                 }
                 else {
@@ -79910,8 +79915,8 @@ var BABYLON;
                 }
             });
         };
-        Database.prototype._loadFileFromDBAsync = function (url, callback, notInDBCallback, useArrayBuffer) {
-            if (this.isSupported && this.db) {
+        Database.prototype._loadFileAsync = function (url, callback, notInDBCallback, useArrayBuffer) {
+            if (this._isSupported && this._db) {
                 var targetStore;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -79920,7 +79925,7 @@ var BABYLON;
                     targetStore = "textures";
                 }
                 var file;
-                var transaction = this.db.transaction([targetStore]);
+                var transaction = this._db.transaction([targetStore]);
                 transaction.oncomplete = function (event) {
                     if (file) {
                         callback(file.data);
@@ -79947,9 +79952,9 @@ var BABYLON;
                 callback();
             }
         };
-        Database.prototype._saveFileIntoDBAsync = function (url, callback, progressCallback, useArrayBuffer, errorCallback) {
+        Database.prototype._saveFileAsync = function (url, callback, progressCallback, useArrayBuffer, errorCallback) {
             var _this = this;
-            if (this.isSupported) {
+            if (this._isSupported) {
                 var targetStore;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -79970,18 +79975,17 @@ var BABYLON;
                 xhr.addEventListener("load", function () {
                     if (xhr.status === 200 || (xhr.status < 400 && BABYLON.Tools.ValidateXHRData(xhr, !useArrayBuffer ? 1 : 6))) {
                         // Blob as response (XHR2)
-                        //fileData = xhr.responseText;
                         fileData = !useArrayBuffer ? xhr.responseText : xhr.response;
-                        if (!_this.hasReachedQuota && _this.db) {
+                        if (!_this._hasReachedQuota && _this._db) {
                             // Open a transaction to the database
-                            var transaction = _this.db.transaction([targetStore], "readwrite");
+                            var transaction = _this._db.transaction([targetStore], "readwrite");
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = function (event) {
                                 try {
                                     //backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                                     var error = event.srcElement['error'];
                                     if (error && error.name === "QuotaExceededError") {
-                                        _this.hasReachedQuota = true;
+                                        _this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -79992,7 +79996,7 @@ var BABYLON;
                             };
                             var newFile;
                             if (targetStore === "scenes") {
-                                newFile = { sceneUrl: url, data: fileData, version: _this.manifestVersionFound };
+                                newFile = { sceneUrl: url, data: fileData, version: _this._manifestVersionFound };
                             }
                             else {
                                 newFile = { textureUrl: url, data: fileData };
@@ -80030,14 +80034,16 @@ var BABYLON;
                 xhr.send();
             }
             else {
-                BABYLON.Tools.Error("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");
+                BABYLON.Tools.Error("Error: IndexedDB not supported by your browser or Babylon.js Database is not open.");
                 callback();
             }
         };
         /** Gets a boolean indicating if the user agent supports blob storage (this value will be updated after creating the first Database object) */
         Database.IsUASupportingBlobStorage = true;
-        /** Gets a boolean indicating if Database storate is enabled */
-        Database.IDBStorageEnabled = true;
+        /**
+         * Gets a boolean indicating if Database storate is enabled (off by default)
+         */
+        Database.IDBStorageEnabled = false;
         Database._ParseURL = function (url) {
             var a = document.createElement('a');
             a.href = url;

+ 119 - 113
dist/preview release/babylon.no-module.max.js

@@ -2039,10 +2039,10 @@ var BABYLON;
          * @param input url string, ArrayBuffer, or Blob to load
          * @param onLoad callback called when the image successfully loads
          * @param onError callback called when the image fails to load
-         * @param database database for caching
+         * @param offlineProvider offline provider for caching
          * @returns the HTMLImageElement of the loaded image
          */
-        Tools.LoadImage = function (input, onLoad, onError, database) {
+        Tools.LoadImage = function (input, onLoad, onError, offlineProvider) {
             var url;
             var usingObjectURL = false;
             if (input instanceof ArrayBuffer) {
@@ -2080,17 +2080,16 @@ var BABYLON;
             };
             img.addEventListener("load", loadHandler);
             img.addEventListener("error", errorHandler);
-            var noIndexedDB = function () {
+            var noOfflineSupport = function () {
                 img.src = url;
             };
-            var loadFromIndexedDB = function () {
-                if (database) {
-                    database.loadImageFromDB(url, img);
+            var loadFromOfflineSupport = function () {
+                if (offlineProvider) {
+                    offlineProvider.loadImage(url, img);
                 }
             };
-            //ANY database to do!
-            if (url.substr(0, 5) !== "data:" && database && database.enableTexturesOffline && BABYLON.Database.IsUASupportingBlobStorage) {
-                database.openAsync(loadFromIndexedDB, noIndexedDB);
+            if (url.substr(0, 5) !== "data:" && offlineProvider && offlineProvider.enableTexturesOffline) {
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport);
             }
             else {
                 if (url.indexOf("file:") !== -1) {
@@ -2114,7 +2113,7 @@ var BABYLON;
                         return img;
                     }
                 }
-                noIndexedDB();
+                noOfflineSupport();
             }
             return img;
         };
@@ -2123,12 +2122,12 @@ var BABYLON;
          * @param url url string, ArrayBuffer, or Blob to load
          * @param onSuccess callback called when the file successfully loads
          * @param onProgress callback called while file is loading (if the server supports this mode)
-         * @param database  database for caching
+         * @param offlineProvider defines the offline provider for caching
          * @param useArrayBuffer defines a boolean indicating that date must be returned as ArrayBuffer
          * @param onError callback called when the file fails to load
          * @returns a file request object
          */
-        Tools.LoadFile = function (url, onSuccess, onProgress, database, useArrayBuffer, onError) {
+        Tools.LoadFile = function (url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError) {
             url = Tools.CleanUrl(url);
             url = Tools.PreprocessUrl(url);
             // If file and file input are set
@@ -2209,8 +2208,8 @@ var BABYLON;
                 retryLoop(0);
             };
             // Caching all files
-            if (database && database.enableSceneOffline) {
-                var noIndexedDB_1 = function (request) {
+            if (offlineProvider && offlineProvider.enableSceneOffline) {
+                var noOfflineSupport_1 = function (request) {
                     if (request && request.status > 400) {
                         if (onError) {
                             onError(request);
@@ -2222,13 +2221,13 @@ var BABYLON;
                         }
                     }
                 };
-                var loadFromIndexedDB = function () {
+                var loadFromOfflineSupport = function () {
                     // TODO: database needs to support aborting and should return a IFileRequest
                     if (aborted) {
                         return;
                     }
-                    if (database) {
-                        database.loadFileFromDB(url, function (data) {
+                    if (offlineProvider) {
+                        offlineProvider.loadFile(url, function (data) {
                             if (!aborted) {
                                 onSuccess(data);
                             }
@@ -2237,10 +2236,10 @@ var BABYLON;
                             if (!aborted) {
                                 onProgress(event);
                             }
-                        } : undefined, noIndexedDB_1, useArrayBuffer);
+                        } : undefined, noOfflineSupport_1, useArrayBuffer);
                     }
                 };
-                database.openAsync(loadFromIndexedDB, noIndexedDB_1);
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport_1);
             }
             else {
                 requestFile();
@@ -12258,7 +12257,7 @@ var BABYLON;
             /** @hidden */
             this._badDesktopOS = false;
             /**
-             * Gets or sets a value indicating if we want to disable texture binding optmization.
+             * Gets or sets a value indicating if we want to disable texture binding optimization.
              * This could be required on some buggy drivers which wants to have textures bound in a progressive order.
              * By default Babylon.js will try to let textures bound where they are and only update the samplers to point where the texture is
              */
@@ -12608,7 +12607,7 @@ var BABYLON;
             // Detect if we are running on a faulty buggy desktop OS.
             this._badDesktopOS = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
             console.log("Babylon.js engine (v" + Engine.Version + ") launched");
-            this.enableOfflineSupport = (BABYLON.Database !== undefined);
+            this.enableOfflineSupport = Engine.OfflineProviderFactory !== undefined;
         }
         Object.defineProperty(Engine, "LastCreatedEngine", {
             /**
@@ -15399,7 +15398,7 @@ var BABYLON;
                     onErrorCallBack(message, exception);
                 }
             };
-            img = BABYLON.Tools.LoadImage(url, onload, onerror, scene ? scene.database : null);
+            img = BABYLON.Tools.LoadImage(url, onload, onerror, scene ? scene.offlineProvider : null);
             if (scene) {
                 scene._addPendingData(img);
             }
@@ -15521,7 +15520,7 @@ var BABYLON;
                     });
                 };
                 if (!buffer) {
-                    this._loadFile(url, callback, undefined, scene ? scene.database : undefined, true, function (request, exception) {
+                    this._loadFile(url, callback, undefined, scene ? scene.offlineProvider : undefined, true, function (request, exception) {
                         onInternalError("Unable to load " + (request ? request.responseURL : url, exception));
                     });
                 }
@@ -15581,11 +15580,11 @@ var BABYLON;
                         onload(buffer);
                     }
                     else {
-                        BABYLON.Tools.LoadImage(url, onload, onInternalError, scene ? scene.database : null);
+                        BABYLON.Tools.LoadImage(url, onload, onInternalError, scene ? scene.offlineProvider : null);
                     }
                 }
                 else if (typeof buffer === "string" || buffer instanceof ArrayBuffer || buffer instanceof Blob) {
-                    BABYLON.Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.database : null);
+                    BABYLON.Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.offlineProvider : null);
                 }
                 else {
                     onload(buffer);
@@ -16930,7 +16929,7 @@ var BABYLON;
             };
             this._loadFile(url, function (data) {
                 internalCallback(data);
-            }, undefined, scene.database, true, onerror);
+            }, undefined, scene.offlineProvider, true, onerror);
             return texture;
         };
         /**
@@ -18199,9 +18198,9 @@ var BABYLON;
             return this._gl.RGBA8;
         };
         /** @hidden */
-        Engine.prototype._loadFile = function (url, onSuccess, onProgress, database, useArrayBuffer, onError) {
+        Engine.prototype._loadFile = function (url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError) {
             var _this = this;
-            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
+            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
                 _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
@@ -18209,12 +18208,12 @@ var BABYLON;
             return request;
         };
         /** @hidden */
-        Engine.prototype._loadFileAsync = function (url, database, useArrayBuffer) {
+        Engine.prototype._loadFileAsync = function (url, offlineProvider, useArrayBuffer) {
             var _this = this;
             return new Promise(function (resolve, reject) {
                 _this._loadFile(url, function (data) {
                     resolve(data);
-                }, undefined, database, useArrayBuffer, function (request, exception) {
+                }, undefined, offlineProvider, useArrayBuffer, function (request, exception) {
                     reject(exception);
                 });
             });
@@ -29901,9 +29900,9 @@ var BABYLON;
             }
         };
         /** @hidden */
-        Scene.prototype._loadFile = function (url, onSuccess, onProgress, useDatabase, useArrayBuffer, onError) {
+        Scene.prototype._loadFile = function (url, onSuccess, onProgress, useOfflineSupport, useArrayBuffer, onError) {
             var _this = this;
-            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, useDatabase ? this.database : undefined, useArrayBuffer, onError);
+            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, useOfflineSupport ? this.offlineProvider : undefined, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
                 _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
@@ -29911,12 +29910,12 @@ var BABYLON;
             return request;
         };
         /** @hidden */
-        Scene.prototype._loadFileAsync = function (url, useDatabase, useArrayBuffer) {
+        Scene.prototype._loadFileAsync = function (url, useOfflineSupport, useArrayBuffer) {
             var _this = this;
             return new Promise(function (resolve, reject) {
                 _this._loadFile(url, function (data) {
                     resolve(data);
-                }, undefined, useDatabase, useArrayBuffer, function (request, exception) {
+                }, undefined, useOfflineSupport, useArrayBuffer, function (request, exception) {
                     reject(exception);
                 });
             });
@@ -33915,7 +33914,7 @@ var BABYLON;
                 });
                 _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
                 scene._removePendingData(_this);
-            }, function () { }, scene.database, getBinaryData);
+            }, function () { }, scene.offlineProvider, getBinaryData);
             return this;
         };
         /**
@@ -34148,7 +34147,7 @@ var BABYLON;
                     onSuccess(_this);
                 }
             };
-            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
+            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.offlineProvider);
             return this;
         };
         /**
@@ -69895,7 +69894,7 @@ var BABYLON;
                 }
                 ground._setReady(true);
             };
-            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
+            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.offlineProvider);
             return ground;
         };
         /**
@@ -70619,7 +70618,7 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
-    // Sets the default audio engine to Babylon JS.
+    // Sets the default audio engine to Babylon.js
     BABYLON.Engine.AudioEngineFactory = function (hostElement) { return new AudioEngine(hostElement); };
     /**
      * This represents the default audio engine used in babylon.
@@ -77732,14 +77731,14 @@ var BABYLON;
                 plugin = registeredPlugin.plugin;
             }
             var useArrayBuffer = registeredPlugin.isBinary;
-            var database;
+            var offlineProvider;
             SceneLoader.OnPluginActivatedObservable.notifyObservers(plugin);
             var dataCallback = function (data, responseURL) {
                 if (scene.isDisposed) {
                     onError("Scene has been disposed");
                     return;
                 }
-                scene.database = database;
+                scene.offlineProvider = offlineProvider;
                 onSuccess(plugin, data, responseURL);
             };
             var request = null;
@@ -77761,7 +77760,7 @@ var BABYLON;
                 }
                 request = BABYLON.Tools.LoadFile(fileInfo.url, dataCallback, onProgress ? function (event) {
                     onProgress(SceneLoaderProgressEvent.FromProgressEvent(event));
-                } : undefined, database, useArrayBuffer, function (request, exception) {
+                } : undefined, offlineProvider, useArrayBuffer, function (request, exception) {
                     onError("Failed to load scene." + (exception ? " " + exception.message : ""), exception);
                 });
             };
@@ -77784,9 +77783,9 @@ var BABYLON;
                     }
                     canUseOfflineSupport = !exceptionFound;
                 }
-                if (canUseOfflineSupport) {
+                if (canUseOfflineSupport && BABYLON.Engine.OfflineProviderFactory) {
                     // Checking if a manifest file has been set for this scene and if offline mode has been requested
-                    database = new BABYLON.Database(fileInfo.url, manifestChecked, engine.disableManifestCheck);
+                    offlineProvider = BABYLON.Engine.OfflineProviderFactory(fileInfo.url, manifestChecked, engine.disableManifestCheck);
                 }
                 else {
                     manifestChecked();
@@ -79427,9 +79426,14 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    // Sets the default offline provider to Babylon.js
+    BABYLON.Engine.OfflineProviderFactory = function (urlToScene, callbackManifestChecked, disableManifestCheck) {
+        if (disableManifestCheck === void 0) { disableManifestCheck = false; }
+        return new Database(urlToScene, callbackManifestChecked, disableManifestCheck);
+    };
     /**
      * Class used to enable access to IndexedDB
-     * @see @https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
+     * @see http://doc.babylonjs.com/how_to/caching_resources_in_indexeddb
      */
     var Database = /** @class */ (function () {
         /**
@@ -79442,25 +79446,25 @@ var BABYLON;
             if (disableManifestCheck === void 0) { disableManifestCheck = false; }
             var _this = this;
             // Handling various flavors of prefixed version of IndexedDB
-            this.idbFactory = (window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
-            this.callbackManifestChecked = callbackManifestChecked;
-            this.currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
-            this.db = null;
+            this._idbFactory = (window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
+            this._callbackManifestChecked = callbackManifestChecked;
+            this._currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
+            this._db = null;
             this._enableSceneOffline = false;
             this._enableTexturesOffline = false;
-            this.manifestVersionFound = 0;
-            this.mustUpdateRessources = false;
-            this.hasReachedQuota = false;
+            this._manifestVersionFound = 0;
+            this._mustUpdateRessources = false;
+            this._hasReachedQuota = false;
             if (!Database.IDBStorageEnabled) {
-                this.callbackManifestChecked(true);
+                this._callbackManifestChecked(true);
             }
             else {
                 if (disableManifestCheck) {
                     this._enableSceneOffline = true;
                     this._enableTexturesOffline = true;
-                    this.manifestVersionFound = 1;
+                    this._manifestVersionFound = 1;
                     BABYLON.Tools.SetImmediate(function () {
-                        _this.callbackManifestChecked(true);
+                        _this._callbackManifestChecked(true);
                     });
                 }
                 else {
@@ -79493,10 +79497,10 @@ var BABYLON;
             var noManifestFile = function () {
                 _this._enableSceneOffline = false;
                 _this._enableTexturesOffline = false;
-                _this.callbackManifestChecked(false);
+                _this._callbackManifestChecked(false);
             };
             var timeStampUsed = false;
-            var manifestURL = this.currentSceneUrl + ".manifest";
+            var manifestURL = this._currentSceneUrl + ".manifest";
             var xhr = new XMLHttpRequest();
             if (navigator.onLine) {
                 // Adding a timestamp to by-pass browsers' cache
@@ -79509,12 +79513,12 @@ var BABYLON;
                     try {
                         var manifestFile = JSON.parse(xhr.response);
                         _this._enableSceneOffline = manifestFile.enableSceneOffline;
-                        _this._enableTexturesOffline = manifestFile.enableTexturesOffline;
+                        _this._enableTexturesOffline = manifestFile.enableTexturesOffline && Database.IsUASupportingBlobStorage;
                         if (manifestFile.version && !isNaN(parseInt(manifestFile.version))) {
-                            _this.manifestVersionFound = manifestFile.version;
+                            _this._manifestVersionFound = manifestFile.version;
                         }
-                        if (_this.callbackManifestChecked) {
-                            _this.callbackManifestChecked(true);
+                        if (_this._callbackManifestChecked) {
+                            _this._callbackManifestChecked(true);
                         }
                     }
                     catch (ex) {
@@ -79530,7 +79534,7 @@ var BABYLON;
                     timeStampUsed = false;
                     // Let's retry without the timeStamp
                     // It could fail when coupled with HTML5 Offline API
-                    var retryManifestURL = _this.currentSceneUrl + ".manifest";
+                    var retryManifestURL = _this._currentSceneUrl + ".manifest";
                     xhr.open("GET", retryManifestURL, true);
                     xhr.send();
                 }
@@ -79543,7 +79547,7 @@ var BABYLON;
             }
             catch (ex) {
                 BABYLON.Tools.Error("Error on XHR send request.");
-                this.callbackManifestChecked(false);
+                this._callbackManifestChecked(false);
             }
         };
         /**
@@ -79551,27 +79555,27 @@ var BABYLON;
          * @param successCallback defines the callback to call on success
          * @param errorCallback defines the callback to call on error
          */
-        Database.prototype.openAsync = function (successCallback, errorCallback) {
+        Database.prototype.open = function (successCallback, errorCallback) {
             var _this = this;
             var handleError = function () {
-                _this.isSupported = false;
+                _this._isSupported = false;
                 if (errorCallback) {
                     errorCallback();
                 }
             };
-            if (!this.idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
+            if (!this._idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
                 // Your browser doesn't support IndexedDB
-                this.isSupported = false;
+                this._isSupported = false;
                 if (errorCallback) {
                     errorCallback();
                 }
             }
             else {
                 // If the DB hasn't been opened or created yet
-                if (!this.db) {
-                    this.hasReachedQuota = false;
-                    this.isSupported = true;
-                    var request = this.idbFactory.open("babylonjs", 1);
+                if (!this._db) {
+                    this._hasReachedQuota = false;
+                    this._isSupported = true;
+                    var request = this._idbFactory.open("babylonjs", 1);
                     // Could occur if user is blocking the quota for the DB and/or doesn't grant access to IndexedDB
                     request.onerror = function (event) {
                         handleError();
@@ -79583,17 +79587,17 @@ var BABYLON;
                     };
                     // DB has been opened successfully
                     request.onsuccess = function (event) {
-                        _this.db = request.result;
+                        _this._db = request.result;
                         successCallback();
                     };
                     // Initialization of the DB. Creating Scenes & Textures stores
                     request.onupgradeneeded = function (event) {
-                        _this.db = (event.target).result;
-                        if (_this.db) {
+                        _this._db = (event.target).result;
+                        if (_this._db) {
                             try {
-                                _this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
-                                _this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
-                                _this.db.createObjectStore("textures", { keyPath: "textureUrl" });
+                                _this._db.createObjectStore("scenes", { keyPath: "sceneUrl" });
+                                _this._db.createObjectStore("versions", { keyPath: "sceneUrl" });
+                                _this._db.createObjectStore("textures", { keyPath: "textureUrl" });
                             }
                             catch (ex) {
                                 BABYLON.Tools.Error("Error while creating object stores. Exception: " + ex.message);
@@ -79615,11 +79619,11 @@ var BABYLON;
          * @param url defines the url to load from
          * @param image defines the target DOM image
          */
-        Database.prototype.loadImageFromDB = function (url, image) {
+        Database.prototype.loadImage = function (url, image) {
             var _this = this;
             var completeURL = Database._ReturnFullUrlLocation(url);
             var saveAndLoadImage = function () {
-                if (!_this.hasReachedQuota && _this.db !== null) {
+                if (!_this._hasReachedQuota && _this._db !== null) {
                     // the texture is not yet in the DB, let's try to save it
                     _this._saveImageIntoDBAsync(completeURL, image);
                 }
@@ -79629,7 +79633,7 @@ var BABYLON;
                     image.src = url;
                 }
             };
-            if (!this.mustUpdateRessources) {
+            if (!this._mustUpdateRessources) {
                 this._loadImageFromDBAsync(completeURL, image, saveAndLoadImage);
             }
             // First time we're download the images or update requested in the manifest file by a version change
@@ -79638,9 +79642,9 @@ var BABYLON;
             }
         };
         Database.prototype._loadImageFromDBAsync = function (url, image, notInDBCallback) {
-            if (this.isSupported && this.db !== null) {
+            if (this._isSupported && this._db !== null) {
                 var texture;
-                var transaction = this.db.transaction(["textures"]);
+                var transaction = this._db.transaction(["textures"]);
                 transaction.onabort = function (event) {
                     image.src = url;
                 };
@@ -79675,7 +79679,7 @@ var BABYLON;
         };
         Database.prototype._saveImageIntoDBAsync = function (url, image) {
             var _this = this;
-            if (this.isSupported) {
+            if (this._isSupported) {
                 // In case of error (type not supported or quota exceeded), we're at least sending back XHR data to allow texture loading later on
                 var generateBlobUrl = function () {
                     var blobTextureURL;
@@ -79698,10 +79702,10 @@ var BABYLON;
                     xhr.open("GET", url, true);
                     xhr.responseType = "blob";
                     xhr.addEventListener("load", function () {
-                        if (xhr.status === 200 && _this.db) {
+                        if (xhr.status === 200 && _this._db) {
                             // Blob as response (XHR2)
                             blob = xhr.response;
-                            var transaction = _this.db.transaction(["textures"], "readwrite");
+                            var transaction = _this._db.transaction(["textures"], "readwrite");
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = function (event) {
                                 try {
@@ -79709,7 +79713,7 @@ var BABYLON;
                                     var srcElement = (event.srcElement || event.target);
                                     var error = srcElement.error;
                                     if (error && error.name === "QuotaExceededError") {
-                                        _this.hasReachedQuota = true;
+                                        _this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -79732,6 +79736,7 @@ var BABYLON;
                                 // "DataCloneError" generated by Chrome when you try to inject blob into IndexedDB
                                 if (ex.code === 25) {
                                     Database.IsUASupportingBlobStorage = false;
+                                    _this._enableTexturesOffline = false;
                                 }
                                 image.src = url;
                             }
@@ -79765,15 +79770,15 @@ var BABYLON;
         };
         Database.prototype._loadVersionFromDBAsync = function (url, callback, updateInDBCallback) {
             var _this = this;
-            if (this.isSupported && this.db) {
+            if (this._isSupported && this._db) {
                 var version;
                 try {
-                    var transaction = this.db.transaction(["versions"]);
+                    var transaction = this._db.transaction(["versions"]);
                     transaction.oncomplete = function (event) {
                         if (version) {
                             // If the version in the JSON file is different from the version in DB
-                            if (_this.manifestVersionFound !== version.data) {
-                                _this.mustUpdateRessources = true;
+                            if (_this._manifestVersionFound !== version.data) {
+                                _this._mustUpdateRessources = true;
                                 updateInDBCallback();
                             }
                             else {
@@ -79782,7 +79787,7 @@ var BABYLON;
                         }
                         // version was not found in DB
                         else {
-                            _this.mustUpdateRessources = true;
+                            _this._mustUpdateRessources = true;
                             updateInDBCallback();
                         }
                     };
@@ -79810,25 +79815,25 @@ var BABYLON;
         };
         Database.prototype._saveVersionIntoDBAsync = function (url, callback) {
             var _this = this;
-            if (this.isSupported && !this.hasReachedQuota && this.db) {
+            if (this._isSupported && !this._hasReachedQuota && this._db) {
                 try {
                     // Open a transaction to the database
-                    var transaction = this.db.transaction(["versions"], "readwrite");
+                    var transaction = this._db.transaction(["versions"], "readwrite");
                     // the transaction could abort because of a QuotaExceededError error
                     transaction.onabort = function (event) {
                         try { //backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                             var error = event.srcElement['error'];
                             if (error && error.name === "QuotaExceededError") {
-                                _this.hasReachedQuota = true;
+                                _this._hasReachedQuota = true;
                             }
                         }
                         catch (ex) { }
                         callback(-1);
                     };
                     transaction.oncomplete = function (event) {
-                        callback(_this.manifestVersionFound);
+                        callback(_this._manifestVersionFound);
                     };
-                    var newVersion = { sceneUrl: url, data: this.manifestVersionFound };
+                    var newVersion = { sceneUrl: url, data: this._manifestVersionFound };
                     // Put the scene into the database
                     var addRequest = transaction.objectStore("versions").put(newVersion);
                     addRequest.onsuccess = function (event) {
@@ -79854,20 +79859,20 @@ var BABYLON;
          * @param errorCallback defines a callback to call on error
          * @param useArrayBuffer defines a boolean to use array buffer instead of text string
          */
-        Database.prototype.loadFileFromDB = function (url, sceneLoaded, progressCallBack, errorCallback, useArrayBuffer) {
+        Database.prototype.loadFile = function (url, sceneLoaded, progressCallBack, errorCallback, useArrayBuffer) {
             var _this = this;
             var completeUrl = Database._ReturnFullUrlLocation(url);
             var saveAndLoadFile = function () {
                 // the scene is not yet in the DB, let's try to save it
-                _this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                _this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
             };
             this._checkVersionFromDB(completeUrl, function (version) {
                 if (version !== -1) {
-                    if (!_this.mustUpdateRessources) {
-                        _this._loadFileFromDBAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
+                    if (!_this._mustUpdateRessources) {
+                        _this._loadFileAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
                     }
                     else {
-                        _this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                        _this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
                     }
                 }
                 else {
@@ -79877,8 +79882,8 @@ var BABYLON;
                 }
             });
         };
-        Database.prototype._loadFileFromDBAsync = function (url, callback, notInDBCallback, useArrayBuffer) {
-            if (this.isSupported && this.db) {
+        Database.prototype._loadFileAsync = function (url, callback, notInDBCallback, useArrayBuffer) {
+            if (this._isSupported && this._db) {
                 var targetStore;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -79887,7 +79892,7 @@ var BABYLON;
                     targetStore = "textures";
                 }
                 var file;
-                var transaction = this.db.transaction([targetStore]);
+                var transaction = this._db.transaction([targetStore]);
                 transaction.oncomplete = function (event) {
                     if (file) {
                         callback(file.data);
@@ -79914,9 +79919,9 @@ var BABYLON;
                 callback();
             }
         };
-        Database.prototype._saveFileIntoDBAsync = function (url, callback, progressCallback, useArrayBuffer, errorCallback) {
+        Database.prototype._saveFileAsync = function (url, callback, progressCallback, useArrayBuffer, errorCallback) {
             var _this = this;
-            if (this.isSupported) {
+            if (this._isSupported) {
                 var targetStore;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -79937,18 +79942,17 @@ var BABYLON;
                 xhr.addEventListener("load", function () {
                     if (xhr.status === 200 || (xhr.status < 400 && BABYLON.Tools.ValidateXHRData(xhr, !useArrayBuffer ? 1 : 6))) {
                         // Blob as response (XHR2)
-                        //fileData = xhr.responseText;
                         fileData = !useArrayBuffer ? xhr.responseText : xhr.response;
-                        if (!_this.hasReachedQuota && _this.db) {
+                        if (!_this._hasReachedQuota && _this._db) {
                             // Open a transaction to the database
-                            var transaction = _this.db.transaction([targetStore], "readwrite");
+                            var transaction = _this._db.transaction([targetStore], "readwrite");
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = function (event) {
                                 try {
                                     //backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                                     var error = event.srcElement['error'];
                                     if (error && error.name === "QuotaExceededError") {
-                                        _this.hasReachedQuota = true;
+                                        _this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -79959,7 +79963,7 @@ var BABYLON;
                             };
                             var newFile;
                             if (targetStore === "scenes") {
-                                newFile = { sceneUrl: url, data: fileData, version: _this.manifestVersionFound };
+                                newFile = { sceneUrl: url, data: fileData, version: _this._manifestVersionFound };
                             }
                             else {
                                 newFile = { textureUrl: url, data: fileData };
@@ -79997,14 +80001,16 @@ var BABYLON;
                 xhr.send();
             }
             else {
-                BABYLON.Tools.Error("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");
+                BABYLON.Tools.Error("Error: IndexedDB not supported by your browser or Babylon.js Database is not open.");
                 callback();
             }
         };
         /** Gets a boolean indicating if the user agent supports blob storage (this value will be updated after creating the first Database object) */
         Database.IsUASupportingBlobStorage = true;
-        /** Gets a boolean indicating if Database storate is enabled */
-        Database.IDBStorageEnabled = true;
+        /**
+         * Gets a boolean indicating if Database storate is enabled (off by default)
+         */
+        Database.IDBStorageEnabled = false;
         Database._ParseURL = function (url) {
             var a = document.createElement('a');
             a.href = url;

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/babylon.worker.js


+ 119 - 113
dist/preview release/es6.js

@@ -2039,10 +2039,10 @@ var BABYLON;
          * @param input url string, ArrayBuffer, or Blob to load
          * @param onLoad callback called when the image successfully loads
          * @param onError callback called when the image fails to load
-         * @param database database for caching
+         * @param offlineProvider offline provider for caching
          * @returns the HTMLImageElement of the loaded image
          */
-        Tools.LoadImage = function (input, onLoad, onError, database) {
+        Tools.LoadImage = function (input, onLoad, onError, offlineProvider) {
             var url;
             var usingObjectURL = false;
             if (input instanceof ArrayBuffer) {
@@ -2080,17 +2080,16 @@ var BABYLON;
             };
             img.addEventListener("load", loadHandler);
             img.addEventListener("error", errorHandler);
-            var noIndexedDB = function () {
+            var noOfflineSupport = function () {
                 img.src = url;
             };
-            var loadFromIndexedDB = function () {
-                if (database) {
-                    database.loadImageFromDB(url, img);
+            var loadFromOfflineSupport = function () {
+                if (offlineProvider) {
+                    offlineProvider.loadImage(url, img);
                 }
             };
-            //ANY database to do!
-            if (url.substr(0, 5) !== "data:" && database && database.enableTexturesOffline && BABYLON.Database.IsUASupportingBlobStorage) {
-                database.openAsync(loadFromIndexedDB, noIndexedDB);
+            if (url.substr(0, 5) !== "data:" && offlineProvider && offlineProvider.enableTexturesOffline) {
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport);
             }
             else {
                 if (url.indexOf("file:") !== -1) {
@@ -2114,7 +2113,7 @@ var BABYLON;
                         return img;
                     }
                 }
-                noIndexedDB();
+                noOfflineSupport();
             }
             return img;
         };
@@ -2123,12 +2122,12 @@ var BABYLON;
          * @param url url string, ArrayBuffer, or Blob to load
          * @param onSuccess callback called when the file successfully loads
          * @param onProgress callback called while file is loading (if the server supports this mode)
-         * @param database  database for caching
+         * @param offlineProvider defines the offline provider for caching
          * @param useArrayBuffer defines a boolean indicating that date must be returned as ArrayBuffer
          * @param onError callback called when the file fails to load
          * @returns a file request object
          */
-        Tools.LoadFile = function (url, onSuccess, onProgress, database, useArrayBuffer, onError) {
+        Tools.LoadFile = function (url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError) {
             url = Tools.CleanUrl(url);
             url = Tools.PreprocessUrl(url);
             // If file and file input are set
@@ -2209,8 +2208,8 @@ var BABYLON;
                 retryLoop(0);
             };
             // Caching all files
-            if (database && database.enableSceneOffline) {
-                var noIndexedDB_1 = function (request) {
+            if (offlineProvider && offlineProvider.enableSceneOffline) {
+                var noOfflineSupport_1 = function (request) {
                     if (request && request.status > 400) {
                         if (onError) {
                             onError(request);
@@ -2222,13 +2221,13 @@ var BABYLON;
                         }
                     }
                 };
-                var loadFromIndexedDB = function () {
+                var loadFromOfflineSupport = function () {
                     // TODO: database needs to support aborting and should return a IFileRequest
                     if (aborted) {
                         return;
                     }
-                    if (database) {
-                        database.loadFileFromDB(url, function (data) {
+                    if (offlineProvider) {
+                        offlineProvider.loadFile(url, function (data) {
                             if (!aborted) {
                                 onSuccess(data);
                             }
@@ -2237,10 +2236,10 @@ var BABYLON;
                             if (!aborted) {
                                 onProgress(event);
                             }
-                        } : undefined, noIndexedDB_1, useArrayBuffer);
+                        } : undefined, noOfflineSupport_1, useArrayBuffer);
                     }
                 };
-                database.openAsync(loadFromIndexedDB, noIndexedDB_1);
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport_1);
             }
             else {
                 requestFile();
@@ -12258,7 +12257,7 @@ var BABYLON;
             /** @hidden */
             this._badDesktopOS = false;
             /**
-             * Gets or sets a value indicating if we want to disable texture binding optmization.
+             * Gets or sets a value indicating if we want to disable texture binding optimization.
              * This could be required on some buggy drivers which wants to have textures bound in a progressive order.
              * By default Babylon.js will try to let textures bound where they are and only update the samplers to point where the texture is
              */
@@ -12608,7 +12607,7 @@ var BABYLON;
             // Detect if we are running on a faulty buggy desktop OS.
             this._badDesktopOS = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
             console.log("Babylon.js engine (v" + Engine.Version + ") launched");
-            this.enableOfflineSupport = (BABYLON.Database !== undefined);
+            this.enableOfflineSupport = Engine.OfflineProviderFactory !== undefined;
         }
         Object.defineProperty(Engine, "LastCreatedEngine", {
             /**
@@ -15399,7 +15398,7 @@ var BABYLON;
                     onErrorCallBack(message, exception);
                 }
             };
-            img = BABYLON.Tools.LoadImage(url, onload, onerror, scene ? scene.database : null);
+            img = BABYLON.Tools.LoadImage(url, onload, onerror, scene ? scene.offlineProvider : null);
             if (scene) {
                 scene._addPendingData(img);
             }
@@ -15521,7 +15520,7 @@ var BABYLON;
                     });
                 };
                 if (!buffer) {
-                    this._loadFile(url, callback, undefined, scene ? scene.database : undefined, true, function (request, exception) {
+                    this._loadFile(url, callback, undefined, scene ? scene.offlineProvider : undefined, true, function (request, exception) {
                         onInternalError("Unable to load " + (request ? request.responseURL : url, exception));
                     });
                 }
@@ -15581,11 +15580,11 @@ var BABYLON;
                         onload(buffer);
                     }
                     else {
-                        BABYLON.Tools.LoadImage(url, onload, onInternalError, scene ? scene.database : null);
+                        BABYLON.Tools.LoadImage(url, onload, onInternalError, scene ? scene.offlineProvider : null);
                     }
                 }
                 else if (typeof buffer === "string" || buffer instanceof ArrayBuffer || buffer instanceof Blob) {
-                    BABYLON.Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.database : null);
+                    BABYLON.Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.offlineProvider : null);
                 }
                 else {
                     onload(buffer);
@@ -16930,7 +16929,7 @@ var BABYLON;
             };
             this._loadFile(url, function (data) {
                 internalCallback(data);
-            }, undefined, scene.database, true, onerror);
+            }, undefined, scene.offlineProvider, true, onerror);
             return texture;
         };
         /**
@@ -18199,9 +18198,9 @@ var BABYLON;
             return this._gl.RGBA8;
         };
         /** @hidden */
-        Engine.prototype._loadFile = function (url, onSuccess, onProgress, database, useArrayBuffer, onError) {
+        Engine.prototype._loadFile = function (url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError) {
             var _this = this;
-            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
+            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
                 _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
@@ -18209,12 +18208,12 @@ var BABYLON;
             return request;
         };
         /** @hidden */
-        Engine.prototype._loadFileAsync = function (url, database, useArrayBuffer) {
+        Engine.prototype._loadFileAsync = function (url, offlineProvider, useArrayBuffer) {
             var _this = this;
             return new Promise(function (resolve, reject) {
                 _this._loadFile(url, function (data) {
                     resolve(data);
-                }, undefined, database, useArrayBuffer, function (request, exception) {
+                }, undefined, offlineProvider, useArrayBuffer, function (request, exception) {
                     reject(exception);
                 });
             });
@@ -29901,9 +29900,9 @@ var BABYLON;
             }
         };
         /** @hidden */
-        Scene.prototype._loadFile = function (url, onSuccess, onProgress, useDatabase, useArrayBuffer, onError) {
+        Scene.prototype._loadFile = function (url, onSuccess, onProgress, useOfflineSupport, useArrayBuffer, onError) {
             var _this = this;
-            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, useDatabase ? this.database : undefined, useArrayBuffer, onError);
+            var request = BABYLON.Tools.LoadFile(url, onSuccess, onProgress, useOfflineSupport ? this.offlineProvider : undefined, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add(function (request) {
                 _this._activeRequests.splice(_this._activeRequests.indexOf(request), 1);
@@ -29911,12 +29910,12 @@ var BABYLON;
             return request;
         };
         /** @hidden */
-        Scene.prototype._loadFileAsync = function (url, useDatabase, useArrayBuffer) {
+        Scene.prototype._loadFileAsync = function (url, useOfflineSupport, useArrayBuffer) {
             var _this = this;
             return new Promise(function (resolve, reject) {
                 _this._loadFile(url, function (data) {
                     resolve(data);
-                }, undefined, useDatabase, useArrayBuffer, function (request, exception) {
+                }, undefined, useOfflineSupport, useArrayBuffer, function (request, exception) {
                     reject(exception);
                 });
             });
@@ -33915,7 +33914,7 @@ var BABYLON;
                 });
                 _this.delayLoadState = BABYLON.Engine.DELAYLOADSTATE_LOADED;
                 scene._removePendingData(_this);
-            }, function () { }, scene.database, getBinaryData);
+            }, function () { }, scene.offlineProvider, getBinaryData);
             return this;
         };
         /**
@@ -34148,7 +34147,7 @@ var BABYLON;
                     onSuccess(_this);
                 }
             };
-            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
+            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.offlineProvider);
             return this;
         };
         /**
@@ -69895,7 +69894,7 @@ var BABYLON;
                 }
                 ground._setReady(true);
             };
-            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.database);
+            BABYLON.Tools.LoadImage(url, onload, function () { }, scene.offlineProvider);
             return ground;
         };
         /**
@@ -70619,7 +70618,7 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
-    // Sets the default audio engine to Babylon JS.
+    // Sets the default audio engine to Babylon.js
     BABYLON.Engine.AudioEngineFactory = function (hostElement) { return new AudioEngine(hostElement); };
     /**
      * This represents the default audio engine used in babylon.
@@ -77732,14 +77731,14 @@ var BABYLON;
                 plugin = registeredPlugin.plugin;
             }
             var useArrayBuffer = registeredPlugin.isBinary;
-            var database;
+            var offlineProvider;
             SceneLoader.OnPluginActivatedObservable.notifyObservers(plugin);
             var dataCallback = function (data, responseURL) {
                 if (scene.isDisposed) {
                     onError("Scene has been disposed");
                     return;
                 }
-                scene.database = database;
+                scene.offlineProvider = offlineProvider;
                 onSuccess(plugin, data, responseURL);
             };
             var request = null;
@@ -77761,7 +77760,7 @@ var BABYLON;
                 }
                 request = BABYLON.Tools.LoadFile(fileInfo.url, dataCallback, onProgress ? function (event) {
                     onProgress(SceneLoaderProgressEvent.FromProgressEvent(event));
-                } : undefined, database, useArrayBuffer, function (request, exception) {
+                } : undefined, offlineProvider, useArrayBuffer, function (request, exception) {
                     onError("Failed to load scene." + (exception ? " " + exception.message : ""), exception);
                 });
             };
@@ -77784,9 +77783,9 @@ var BABYLON;
                     }
                     canUseOfflineSupport = !exceptionFound;
                 }
-                if (canUseOfflineSupport) {
+                if (canUseOfflineSupport && BABYLON.Engine.OfflineProviderFactory) {
                     // Checking if a manifest file has been set for this scene and if offline mode has been requested
-                    database = new BABYLON.Database(fileInfo.url, manifestChecked, engine.disableManifestCheck);
+                    offlineProvider = BABYLON.Engine.OfflineProviderFactory(fileInfo.url, manifestChecked, engine.disableManifestCheck);
                 }
                 else {
                     manifestChecked();
@@ -79427,9 +79426,14 @@ var BABYLON;
 
 var BABYLON;
 (function (BABYLON) {
+    // Sets the default offline provider to Babylon.js
+    BABYLON.Engine.OfflineProviderFactory = function (urlToScene, callbackManifestChecked, disableManifestCheck) {
+        if (disableManifestCheck === void 0) { disableManifestCheck = false; }
+        return new Database(urlToScene, callbackManifestChecked, disableManifestCheck);
+    };
     /**
      * Class used to enable access to IndexedDB
-     * @see @https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
+     * @see http://doc.babylonjs.com/how_to/caching_resources_in_indexeddb
      */
     var Database = /** @class */ (function () {
         /**
@@ -79442,25 +79446,25 @@ var BABYLON;
             if (disableManifestCheck === void 0) { disableManifestCheck = false; }
             var _this = this;
             // Handling various flavors of prefixed version of IndexedDB
-            this.idbFactory = (window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
-            this.callbackManifestChecked = callbackManifestChecked;
-            this.currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
-            this.db = null;
+            this._idbFactory = (window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
+            this._callbackManifestChecked = callbackManifestChecked;
+            this._currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
+            this._db = null;
             this._enableSceneOffline = false;
             this._enableTexturesOffline = false;
-            this.manifestVersionFound = 0;
-            this.mustUpdateRessources = false;
-            this.hasReachedQuota = false;
+            this._manifestVersionFound = 0;
+            this._mustUpdateRessources = false;
+            this._hasReachedQuota = false;
             if (!Database.IDBStorageEnabled) {
-                this.callbackManifestChecked(true);
+                this._callbackManifestChecked(true);
             }
             else {
                 if (disableManifestCheck) {
                     this._enableSceneOffline = true;
                     this._enableTexturesOffline = true;
-                    this.manifestVersionFound = 1;
+                    this._manifestVersionFound = 1;
                     BABYLON.Tools.SetImmediate(function () {
-                        _this.callbackManifestChecked(true);
+                        _this._callbackManifestChecked(true);
                     });
                 }
                 else {
@@ -79493,10 +79497,10 @@ var BABYLON;
             var noManifestFile = function () {
                 _this._enableSceneOffline = false;
                 _this._enableTexturesOffline = false;
-                _this.callbackManifestChecked(false);
+                _this._callbackManifestChecked(false);
             };
             var timeStampUsed = false;
-            var manifestURL = this.currentSceneUrl + ".manifest";
+            var manifestURL = this._currentSceneUrl + ".manifest";
             var xhr = new XMLHttpRequest();
             if (navigator.onLine) {
                 // Adding a timestamp to by-pass browsers' cache
@@ -79509,12 +79513,12 @@ var BABYLON;
                     try {
                         var manifestFile = JSON.parse(xhr.response);
                         _this._enableSceneOffline = manifestFile.enableSceneOffline;
-                        _this._enableTexturesOffline = manifestFile.enableTexturesOffline;
+                        _this._enableTexturesOffline = manifestFile.enableTexturesOffline && Database.IsUASupportingBlobStorage;
                         if (manifestFile.version && !isNaN(parseInt(manifestFile.version))) {
-                            _this.manifestVersionFound = manifestFile.version;
+                            _this._manifestVersionFound = manifestFile.version;
                         }
-                        if (_this.callbackManifestChecked) {
-                            _this.callbackManifestChecked(true);
+                        if (_this._callbackManifestChecked) {
+                            _this._callbackManifestChecked(true);
                         }
                     }
                     catch (ex) {
@@ -79530,7 +79534,7 @@ var BABYLON;
                     timeStampUsed = false;
                     // Let's retry without the timeStamp
                     // It could fail when coupled with HTML5 Offline API
-                    var retryManifestURL = _this.currentSceneUrl + ".manifest";
+                    var retryManifestURL = _this._currentSceneUrl + ".manifest";
                     xhr.open("GET", retryManifestURL, true);
                     xhr.send();
                 }
@@ -79543,7 +79547,7 @@ var BABYLON;
             }
             catch (ex) {
                 BABYLON.Tools.Error("Error on XHR send request.");
-                this.callbackManifestChecked(false);
+                this._callbackManifestChecked(false);
             }
         };
         /**
@@ -79551,27 +79555,27 @@ var BABYLON;
          * @param successCallback defines the callback to call on success
          * @param errorCallback defines the callback to call on error
          */
-        Database.prototype.openAsync = function (successCallback, errorCallback) {
+        Database.prototype.open = function (successCallback, errorCallback) {
             var _this = this;
             var handleError = function () {
-                _this.isSupported = false;
+                _this._isSupported = false;
                 if (errorCallback) {
                     errorCallback();
                 }
             };
-            if (!this.idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
+            if (!this._idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
                 // Your browser doesn't support IndexedDB
-                this.isSupported = false;
+                this._isSupported = false;
                 if (errorCallback) {
                     errorCallback();
                 }
             }
             else {
                 // If the DB hasn't been opened or created yet
-                if (!this.db) {
-                    this.hasReachedQuota = false;
-                    this.isSupported = true;
-                    var request = this.idbFactory.open("babylonjs", 1);
+                if (!this._db) {
+                    this._hasReachedQuota = false;
+                    this._isSupported = true;
+                    var request = this._idbFactory.open("babylonjs", 1);
                     // Could occur if user is blocking the quota for the DB and/or doesn't grant access to IndexedDB
                     request.onerror = function (event) {
                         handleError();
@@ -79583,17 +79587,17 @@ var BABYLON;
                     };
                     // DB has been opened successfully
                     request.onsuccess = function (event) {
-                        _this.db = request.result;
+                        _this._db = request.result;
                         successCallback();
                     };
                     // Initialization of the DB. Creating Scenes & Textures stores
                     request.onupgradeneeded = function (event) {
-                        _this.db = (event.target).result;
-                        if (_this.db) {
+                        _this._db = (event.target).result;
+                        if (_this._db) {
                             try {
-                                _this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
-                                _this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
-                                _this.db.createObjectStore("textures", { keyPath: "textureUrl" });
+                                _this._db.createObjectStore("scenes", { keyPath: "sceneUrl" });
+                                _this._db.createObjectStore("versions", { keyPath: "sceneUrl" });
+                                _this._db.createObjectStore("textures", { keyPath: "textureUrl" });
                             }
                             catch (ex) {
                                 BABYLON.Tools.Error("Error while creating object stores. Exception: " + ex.message);
@@ -79615,11 +79619,11 @@ var BABYLON;
          * @param url defines the url to load from
          * @param image defines the target DOM image
          */
-        Database.prototype.loadImageFromDB = function (url, image) {
+        Database.prototype.loadImage = function (url, image) {
             var _this = this;
             var completeURL = Database._ReturnFullUrlLocation(url);
             var saveAndLoadImage = function () {
-                if (!_this.hasReachedQuota && _this.db !== null) {
+                if (!_this._hasReachedQuota && _this._db !== null) {
                     // the texture is not yet in the DB, let's try to save it
                     _this._saveImageIntoDBAsync(completeURL, image);
                 }
@@ -79629,7 +79633,7 @@ var BABYLON;
                     image.src = url;
                 }
             };
-            if (!this.mustUpdateRessources) {
+            if (!this._mustUpdateRessources) {
                 this._loadImageFromDBAsync(completeURL, image, saveAndLoadImage);
             }
             // First time we're download the images or update requested in the manifest file by a version change
@@ -79638,9 +79642,9 @@ var BABYLON;
             }
         };
         Database.prototype._loadImageFromDBAsync = function (url, image, notInDBCallback) {
-            if (this.isSupported && this.db !== null) {
+            if (this._isSupported && this._db !== null) {
                 var texture;
-                var transaction = this.db.transaction(["textures"]);
+                var transaction = this._db.transaction(["textures"]);
                 transaction.onabort = function (event) {
                     image.src = url;
                 };
@@ -79675,7 +79679,7 @@ var BABYLON;
         };
         Database.prototype._saveImageIntoDBAsync = function (url, image) {
             var _this = this;
-            if (this.isSupported) {
+            if (this._isSupported) {
                 // In case of error (type not supported or quota exceeded), we're at least sending back XHR data to allow texture loading later on
                 var generateBlobUrl = function () {
                     var blobTextureURL;
@@ -79698,10 +79702,10 @@ var BABYLON;
                     xhr.open("GET", url, true);
                     xhr.responseType = "blob";
                     xhr.addEventListener("load", function () {
-                        if (xhr.status === 200 && _this.db) {
+                        if (xhr.status === 200 && _this._db) {
                             // Blob as response (XHR2)
                             blob = xhr.response;
-                            var transaction = _this.db.transaction(["textures"], "readwrite");
+                            var transaction = _this._db.transaction(["textures"], "readwrite");
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = function (event) {
                                 try {
@@ -79709,7 +79713,7 @@ var BABYLON;
                                     var srcElement = (event.srcElement || event.target);
                                     var error = srcElement.error;
                                     if (error && error.name === "QuotaExceededError") {
-                                        _this.hasReachedQuota = true;
+                                        _this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -79732,6 +79736,7 @@ var BABYLON;
                                 // "DataCloneError" generated by Chrome when you try to inject blob into IndexedDB
                                 if (ex.code === 25) {
                                     Database.IsUASupportingBlobStorage = false;
+                                    _this._enableTexturesOffline = false;
                                 }
                                 image.src = url;
                             }
@@ -79765,15 +79770,15 @@ var BABYLON;
         };
         Database.prototype._loadVersionFromDBAsync = function (url, callback, updateInDBCallback) {
             var _this = this;
-            if (this.isSupported && this.db) {
+            if (this._isSupported && this._db) {
                 var version;
                 try {
-                    var transaction = this.db.transaction(["versions"]);
+                    var transaction = this._db.transaction(["versions"]);
                     transaction.oncomplete = function (event) {
                         if (version) {
                             // If the version in the JSON file is different from the version in DB
-                            if (_this.manifestVersionFound !== version.data) {
-                                _this.mustUpdateRessources = true;
+                            if (_this._manifestVersionFound !== version.data) {
+                                _this._mustUpdateRessources = true;
                                 updateInDBCallback();
                             }
                             else {
@@ -79782,7 +79787,7 @@ var BABYLON;
                         }
                         // version was not found in DB
                         else {
-                            _this.mustUpdateRessources = true;
+                            _this._mustUpdateRessources = true;
                             updateInDBCallback();
                         }
                     };
@@ -79810,25 +79815,25 @@ var BABYLON;
         };
         Database.prototype._saveVersionIntoDBAsync = function (url, callback) {
             var _this = this;
-            if (this.isSupported && !this.hasReachedQuota && this.db) {
+            if (this._isSupported && !this._hasReachedQuota && this._db) {
                 try {
                     // Open a transaction to the database
-                    var transaction = this.db.transaction(["versions"], "readwrite");
+                    var transaction = this._db.transaction(["versions"], "readwrite");
                     // the transaction could abort because of a QuotaExceededError error
                     transaction.onabort = function (event) {
                         try { //backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                             var error = event.srcElement['error'];
                             if (error && error.name === "QuotaExceededError") {
-                                _this.hasReachedQuota = true;
+                                _this._hasReachedQuota = true;
                             }
                         }
                         catch (ex) { }
                         callback(-1);
                     };
                     transaction.oncomplete = function (event) {
-                        callback(_this.manifestVersionFound);
+                        callback(_this._manifestVersionFound);
                     };
-                    var newVersion = { sceneUrl: url, data: this.manifestVersionFound };
+                    var newVersion = { sceneUrl: url, data: this._manifestVersionFound };
                     // Put the scene into the database
                     var addRequest = transaction.objectStore("versions").put(newVersion);
                     addRequest.onsuccess = function (event) {
@@ -79854,20 +79859,20 @@ var BABYLON;
          * @param errorCallback defines a callback to call on error
          * @param useArrayBuffer defines a boolean to use array buffer instead of text string
          */
-        Database.prototype.loadFileFromDB = function (url, sceneLoaded, progressCallBack, errorCallback, useArrayBuffer) {
+        Database.prototype.loadFile = function (url, sceneLoaded, progressCallBack, errorCallback, useArrayBuffer) {
             var _this = this;
             var completeUrl = Database._ReturnFullUrlLocation(url);
             var saveAndLoadFile = function () {
                 // the scene is not yet in the DB, let's try to save it
-                _this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                _this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
             };
             this._checkVersionFromDB(completeUrl, function (version) {
                 if (version !== -1) {
-                    if (!_this.mustUpdateRessources) {
-                        _this._loadFileFromDBAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
+                    if (!_this._mustUpdateRessources) {
+                        _this._loadFileAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
                     }
                     else {
-                        _this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                        _this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
                     }
                 }
                 else {
@@ -79877,8 +79882,8 @@ var BABYLON;
                 }
             });
         };
-        Database.prototype._loadFileFromDBAsync = function (url, callback, notInDBCallback, useArrayBuffer) {
-            if (this.isSupported && this.db) {
+        Database.prototype._loadFileAsync = function (url, callback, notInDBCallback, useArrayBuffer) {
+            if (this._isSupported && this._db) {
                 var targetStore;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -79887,7 +79892,7 @@ var BABYLON;
                     targetStore = "textures";
                 }
                 var file;
-                var transaction = this.db.transaction([targetStore]);
+                var transaction = this._db.transaction([targetStore]);
                 transaction.oncomplete = function (event) {
                     if (file) {
                         callback(file.data);
@@ -79914,9 +79919,9 @@ var BABYLON;
                 callback();
             }
         };
-        Database.prototype._saveFileIntoDBAsync = function (url, callback, progressCallback, useArrayBuffer, errorCallback) {
+        Database.prototype._saveFileAsync = function (url, callback, progressCallback, useArrayBuffer, errorCallback) {
             var _this = this;
-            if (this.isSupported) {
+            if (this._isSupported) {
                 var targetStore;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -79937,18 +79942,17 @@ var BABYLON;
                 xhr.addEventListener("load", function () {
                     if (xhr.status === 200 || (xhr.status < 400 && BABYLON.Tools.ValidateXHRData(xhr, !useArrayBuffer ? 1 : 6))) {
                         // Blob as response (XHR2)
-                        //fileData = xhr.responseText;
                         fileData = !useArrayBuffer ? xhr.responseText : xhr.response;
-                        if (!_this.hasReachedQuota && _this.db) {
+                        if (!_this._hasReachedQuota && _this._db) {
                             // Open a transaction to the database
-                            var transaction = _this.db.transaction([targetStore], "readwrite");
+                            var transaction = _this._db.transaction([targetStore], "readwrite");
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = function (event) {
                                 try {
                                     //backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                                     var error = event.srcElement['error'];
                                     if (error && error.name === "QuotaExceededError") {
-                                        _this.hasReachedQuota = true;
+                                        _this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -79959,7 +79963,7 @@ var BABYLON;
                             };
                             var newFile;
                             if (targetStore === "scenes") {
-                                newFile = { sceneUrl: url, data: fileData, version: _this.manifestVersionFound };
+                                newFile = { sceneUrl: url, data: fileData, version: _this._manifestVersionFound };
                             }
                             else {
                                 newFile = { textureUrl: url, data: fileData };
@@ -79997,14 +80001,16 @@ var BABYLON;
                 xhr.send();
             }
             else {
-                BABYLON.Tools.Error("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");
+                BABYLON.Tools.Error("Error: IndexedDB not supported by your browser or Babylon.js Database is not open.");
                 callback();
             }
         };
         /** Gets a boolean indicating if the user agent supports blob storage (this value will be updated after creating the first Database object) */
         Database.IsUASupportingBlobStorage = true;
-        /** Gets a boolean indicating if Database storate is enabled */
-        Database.IDBStorageEnabled = true;
+        /**
+         * Gets a boolean indicating if Database storate is enabled (off by default)
+         */
+        Database.IDBStorageEnabled = false;
         Database._ParseURL = function (url) {
             var a = document.createElement('a');
             a.href = url;

+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -2267,7 +2267,7 @@ var BABYLON;
                                         }
                                     }
                                 }
-                            }, _this.babylonScene.database, true, function (request, exception) {
+                            }, _this.babylonScene.offlineProvider, true, function (request, exception) {
                                 if (!_this._disposed) {
                                     reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
                                 }

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -4475,7 +4475,7 @@ var BABYLON;
                                         }
                                     }
                                 }
-                            }, _this.babylonScene.database, true, function (request, exception) {
+                            }, _this.babylonScene.offlineProvider, true, function (request, exception) {
                                 if (!_this._disposed) {
                                     reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
                                 }

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js

@@ -5537,7 +5537,7 @@ var BABYLON;
                                         }
                                     }
                                 }
-                            }, _this.babylonScene.database, true, function (request, exception) {
+                            }, _this.babylonScene.offlineProvider, true, function (request, exception) {
                                 if (!_this._disposed) {
                                     reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
                                 }

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


+ 1 - 1
dist/preview release/viewer/babylon.viewer.d.ts

@@ -200,7 +200,7 @@ declare module BabylonViewer {
 }
 declare module BabylonViewer {
     /**
-        * The AbstractViewr is the center of Babylon's viewer.
+        * The AbstractViewer is the center of Babylon's viewer.
         * It is the basic implementation of the default viewer and is responsible of loading and showing the model and the templates
         */
     export abstract class AbstractViewer {

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


File diff ditekan karena terlalu besar
+ 3 - 3
dist/preview release/viewer/babylon.viewer.max.js


+ 1 - 1
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -242,7 +242,7 @@ declare module 'babylonjs-viewer/viewer/viewer' {
     import { ViewerModel } from 'babylonjs-viewer/model/viewerModel';
     import { TemplateManager } from 'babylonjs-viewer/templating/templateManager';
     /**
-        * The AbstractViewr is the center of Babylon's viewer.
+        * The AbstractViewer is the center of Babylon's viewer.
         * It is the basic implementation of the default viewer and is responsible of loading and showing the model and the templates
         */
     export abstract class AbstractViewer {

+ 4 - 0
dist/preview release/what's new.md

@@ -14,6 +14,7 @@
 
 - Refactor of the SolidParticleSystem code for performance and code quality improvement ([barroij](https://github.com/barroij))
 - Added utility function `Tools.BuildArray` for array initialisation ([barroij](https://github.com/barroij))
+- Introduced a new `IOfflineSupport` interface to hide IndexedDB ([Deltakosh](https://github.com/deltakosh))
 
 ### glTF Loader
 
@@ -34,3 +35,6 @@
 ### Loaders
 
 ## Breaking changes
+
+- `Database.IDBStorageEnabled` is now false by default ([Deltakosh](https://github.com/deltakosh))
+- `Database.openAsync` was renamed by `Database.open`

+ 15 - 15
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -30,7 +30,7 @@ module BABYLON.GLTF2 {
                 throw new Error(`${context}: Failed to find index (${index})`);
             }
 
-           return array[index];
+            return array[index];
         }
 
         /**
@@ -431,7 +431,7 @@ module BABYLON.GLTF2 {
 
             this.logClose();
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         private _forEachPrimitive(node: Loader.INode, callback: (babylonMesh: Mesh) => void): void {
@@ -533,7 +533,7 @@ module BABYLON.GLTF2 {
          * @param assign A function called synchronously after parsing the glTF properties
          * @returns A promise that resolves with the loaded Babylon mesh when the load is complete
          */
-        public loadNodeAsync(context: string, node: Loader.INode, assign: (babylonMesh: Mesh) => void = () => {}): Promise<Mesh> {
+        public loadNodeAsync(context: string, node: Loader.INode, assign: (babylonMesh: Mesh) => void = () => { }): Promise<Mesh> {
             const extensionPromise = this._extensionsLoadNodeAsync(context, node, assign);
             if (extensionPromise) {
                 return extensionPromise;
@@ -661,7 +661,7 @@ module BABYLON.GLTF2 {
 
             this.logClose();
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         private _loadVertexDataAsync(context: string, primitive: Loader.IMeshPrimitive, babylonMesh: Mesh): Promise<Geometry> {
@@ -760,7 +760,7 @@ module BABYLON.GLTF2 {
                 promises.push(this._loadMorphTargetVertexDataAsync(`${context}/targets/${index}`, babylonGeometry, primitive.targets[index], babylonMorphTarget));
             }
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         private _loadMorphTargetVertexDataAsync(context: string, babylonGeometry: Geometry, attributes: { [name: string]: number }, babylonMorphTarget: MorphTarget): Promise<void> {
@@ -811,7 +811,7 @@ module BABYLON.GLTF2 {
                 babylonMorphTarget.setTangents(data);
             });
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         private static _LoadTransform(node: Loader.INode, babylonNode: TransformNode): void {
@@ -938,7 +938,7 @@ module BABYLON.GLTF2 {
          * @param assign A function called synchronously after parsing the glTF properties
          * @returns A promise that resolves with the loaded Babylon camera when the load is complete
          */
-        public loadCameraAsync(context: string, camera: Loader.ICamera, assign: (babylonCamera: Camera) => void = () => {}): Promise<Camera> {
+        public loadCameraAsync(context: string, camera: Loader.ICamera, assign: (babylonCamera: Camera) => void = () => { }): Promise<Camera> {
             const extensionPromise = this._extensionsLoadCameraAsync(context, camera, assign);
             if (extensionPromise) {
                 return extensionPromise;
@@ -1003,7 +1003,7 @@ module BABYLON.GLTF2 {
                 promises.push(this.loadAnimationAsync(`#/animations/${animation.index}`, animation));
             }
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         /**
@@ -1415,11 +1415,11 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         /** @hidden */
-        public _loadMaterialAsync(context: string, material: Loader.IMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void = () => {}): Promise<Material> {
+        public _loadMaterialAsync(context: string, material: Loader.IMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void = () => { }): Promise<Material> {
             const extensionPromise = this._extensionsLoadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign);
             if (extensionPromise) {
                 return extensionPromise;
@@ -1514,7 +1514,7 @@ module BABYLON.GLTF2 {
 
             this.loadMaterialAlphaProperties(context, material, babylonMaterial);
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         /**
@@ -1566,7 +1566,7 @@ module BABYLON.GLTF2 {
                 }));
             }
 
-            return Promise.all(promises).then(() => {});
+            return Promise.all(promises).then(() => { });
         }
 
         /**
@@ -1616,7 +1616,7 @@ module BABYLON.GLTF2 {
          * @param assign A function called synchronously after parsing the glTF properties
          * @returns A promise that resolves with the loaded Babylon texture when the load is complete
          */
-        public loadTextureInfoAsync(context: string, textureInfo: Loader.ITextureInfo, assign: (babylonTexture: BaseTexture) => void = () => {}): Promise<BaseTexture> {
+        public loadTextureInfoAsync(context: string, textureInfo: Loader.ITextureInfo, assign: (babylonTexture: BaseTexture) => void = () => { }): Promise<BaseTexture> {
             const extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
             if (extensionPromise) {
                 return extensionPromise;
@@ -1635,7 +1635,7 @@ module BABYLON.GLTF2 {
             return promise;
         }
 
-        private _loadTextureAsync(context: string, texture: Loader.ITexture, assign: (babylonTexture: BaseTexture) => void = () => {}): Promise<BaseTexture> {
+        private _loadTextureAsync(context: string, texture: Loader.ITexture, assign: (babylonTexture: BaseTexture) => void = () => { }): Promise<BaseTexture> {
             const promises = new Array<Promise<any>>();
 
             this.logOpen(`${context} ${texture.name || ""}`);
@@ -1763,7 +1763,7 @@ module BABYLON.GLTF2 {
                                     }
                                 }
                             }
-                        }, this.babylonScene.database, true, (request, exception) => {
+                        }, this.babylonScene.offlineProvider, true, (request, exception) => {
                             if (!this._disposed) {
                                 reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
                             }

+ 2 - 2
src/Audio/babylon.audioEngine.ts

@@ -70,7 +70,7 @@ module BABYLON {
         unlock(): void;
     }
 
-    // Sets the default audio engine to Babylon JS.
+    // Sets the default audio engine to Babylon.js
     Engine.AudioEngineFactory = (hostElement: Nullable<HTMLElement>) => { return new AudioEngine(hostElement); };
 
     /**
@@ -78,7 +78,7 @@ module BABYLON {
      * It is responsible to play, synchronize and analyse sounds throughout the  application.
      * @see http://doc.babylonjs.com/how_to/playing_sounds_and_music
      */
-    export class AudioEngine implements IAudioEngine{
+    export class AudioEngine implements IAudioEngine {
         private _audioContext: Nullable<AudioContext> = null;
         private _audioContextInitialized = false;
         private _muteButton: Nullable<HTMLButtonElement> = null;

+ 19 - 14
src/Engine/babylon.engine.ts

@@ -662,7 +662,7 @@ module BABYLON {
         public _badDesktopOS = false;
 
         /**
-         * Gets or sets a value indicating if we want to disable texture binding optmization.
+         * Gets or sets a value indicating if we want to disable texture binding optimization.
          * This could be required on some buggy drivers which wants to have textures bound in a progressive order.
          * By default Babylon.js will try to let textures bound where they are and only update the samplers to point where the texture is
          */
@@ -676,12 +676,17 @@ module BABYLON {
         public static audioEngine: IAudioEngine;
 
         /**
-         * Default AudioEngine Factory responsible of creating the Audio Engine.
-         * By default, this will create a BabylonJS Audio Engine if the workload
-         * has been embedded.
+         * Default AudioEngine factory responsible of creating the Audio Engine.
+         * By default, this will create a BabylonJS Audio Engine if the workload has been embedded.
          */
         public static AudioEngineFactory: (hostElement: Nullable<HTMLElement>) => IAudioEngine;
 
+        /**
+         * Default offline support factory responsible of creating a tool used to store data locally.
+         * By default, this will create a Database object if the workload has been embedded.
+         */
+        public static OfflineProviderFactory: (urlToScene: string, callbackManifestChecked: (checked: boolean) => any, disableManifestCheck: boolean) => IOfflineProvider;
+
         // Focus
         private _onFocus: () => void;
         private _onBlur: () => void;
@@ -1222,7 +1227,7 @@ module BABYLON {
 
             console.log("Babylon.js engine (v" + Engine.Version + ") launched");
 
-            this.enableOfflineSupport = (Database !== undefined);
+            this.enableOfflineSupport = Engine.OfflineProviderFactory !== undefined;
         }
 
         private _rebuildInternalTextures(): void {
@@ -4171,7 +4176,7 @@ module BABYLON {
                 }
             };
 
-            img = Tools.LoadImage(url, onload, onerror, scene ? scene.database : null);
+            img = Tools.LoadImage(url, onload, onerror, scene ? scene.offlineProvider : null);
             if (scene) {
                 scene._addPendingData(img);
             }
@@ -4307,7 +4312,7 @@ module BABYLON {
                 };
 
                 if (!buffer) {
-                    this._loadFile(url, callback, undefined, scene ? scene.database : undefined, true, (request?: XMLHttpRequest, exception?: any) => {
+                    this._loadFile(url, callback, undefined, scene ? scene.offlineProvider : undefined, true, (request?: XMLHttpRequest, exception?: any) => {
                         onInternalError("Unable to load " + (request ? request.responseURL : url, exception));
                     });
                 } else {
@@ -4376,11 +4381,11 @@ module BABYLON {
                     if (buffer instanceof HTMLImageElement) {
                         onload(buffer);
                     } else {
-                        Tools.LoadImage(url, onload, onInternalError, scene ? scene.database : null);
+                        Tools.LoadImage(url, onload, onInternalError, scene ? scene.offlineProvider : null);
                     }
                 }
                 else if (typeof buffer === "string" || buffer instanceof ArrayBuffer || buffer instanceof Blob) {
-                    Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.database : null);
+                    Tools.LoadImage(buffer, onload, onInternalError, scene ? scene.offlineProvider : null);
                 }
                 else {
                     onload(<HTMLImageElement>buffer);
@@ -6015,7 +6020,7 @@ module BABYLON {
 
             this._loadFile(url, (data) => {
                 internalCallback(data);
-            }, undefined, scene.database, true, onerror);
+            }, undefined, scene.offlineProvider, true, onerror);
 
             return texture;
         }
@@ -7462,8 +7467,8 @@ module BABYLON {
         }
 
         /** @hidden */
-        public _loadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, database?: Database, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
-            let request = Tools.LoadFile(url, onSuccess, onProgress, database, useArrayBuffer, onError);
+        public _loadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, offlineProvider?: IOfflineProvider, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
+            let request = Tools.LoadFile(url, onSuccess, onProgress, offlineProvider, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add((request) => {
                 this._activeRequests.splice(this._activeRequests.indexOf(request), 1);
@@ -7472,11 +7477,11 @@ module BABYLON {
         }
 
         /** @hidden */
-        public _loadFileAsync(url: string, database?: Database, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
+        public _loadFileAsync(url: string, offlineProvider?: IOfflineProvider, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
             return new Promise((resolve, reject) => {
                 this._loadFile(url, (data) => {
                     resolve(data);
-                }, undefined, database, useArrayBuffer, (request, exception) => {
+                }, undefined, offlineProvider, useArrayBuffer, (request, exception) => {
                     reject(exception);
                 });
             });

+ 5 - 5
src/Loading/babylon.sceneLoader.ts

@@ -355,7 +355,7 @@ module BABYLON {
             }
 
             let useArrayBuffer = registeredPlugin.isBinary;
-            let database: Database;
+            let offlineProvider: IOfflineProvider;
 
             SceneLoader.OnPluginActivatedObservable.notifyObservers(plugin);
 
@@ -365,7 +365,7 @@ module BABYLON {
                     return;
                 }
 
-                scene.database = database;
+                scene.offlineProvider = offlineProvider;
 
                 onSuccess(plugin, data, responseURL);
             };
@@ -393,7 +393,7 @@ module BABYLON {
 
                 request = Tools.LoadFile(fileInfo.url, dataCallback, onProgress ? (event) => {
                     onProgress(SceneLoaderProgressEvent.FromProgressEvent(event));
-                } : undefined, database, useArrayBuffer, (request, exception) => {
+                } : undefined, offlineProvider, useArrayBuffer, (request, exception) => {
                     onError("Failed to load scene." + (exception ? " " + exception.message : ""), exception);
                 });
             };
@@ -419,9 +419,9 @@ module BABYLON {
                     canUseOfflineSupport = !exceptionFound;
                 }
 
-                if (canUseOfflineSupport) {
+                if (canUseOfflineSupport && Engine.OfflineProviderFactory) {
                     // Checking if a manifest file has been set for this scene and if offline mode has been requested
-                    database = new Database(fileInfo.url, manifestChecked, engine.disableManifestCheck);
+                    offlineProvider = Engine.OfflineProviderFactory(fileInfo.url, manifestChecked, engine.disableManifestCheck);
                 }
                 else {
                     manifestChecked();

+ 237 - 237
src/Mesh/babylon.mesh.ts

@@ -1666,7 +1666,7 @@ module BABYLON {
             let matricesWeights = (<FloatArray>this.getVerticesData(VertexBuffer.MatricesWeightsKind));
             let numWeights = matricesWeights.length;
 
-            for (var a = 0; a  < numWeights; a += 4) {
+            for (var a = 0; a < numWeights; a += 4) {
                 // accumulate weights
                 var t = matricesWeights[a] + matricesWeights[a + 1] + matricesWeights[a + 2] + matricesWeights[a + 3];
                 t += matricesWeightsExtra[a] + matricesWeightsExtra[a + 1] + matricesWeightsExtra[a + 2] + matricesWeightsExtra[a + 3];
@@ -1697,31 +1697,31 @@ module BABYLON {
          * the user know there was an issue with importing the mesh
          * @returns a validation object with skinned, valid and report string
          */
-        public validateSkinning() : {skinned: boolean, valid: boolean, report: string} {
+        public validateSkinning(): { skinned: boolean, valid: boolean, report: string } {
 
             let matricesWeightsExtra = (<FloatArray>this.getVerticesData(VertexBuffer.MatricesWeightsExtraKind));
             let matricesWeights = (<FloatArray>this.getVerticesData(VertexBuffer.MatricesWeightsKind));
             if (matricesWeights === null || this.skeleton == null) {
-                return {skinned: false, valid: true, report: "not skinned"};
+                return { skinned: false, valid: true, report: "not skinned" };
             }
 
             let numWeights = matricesWeights.length;
-            let numberNotSorted : number = 0;
-            let missingWeights : number  = 0;
-            let maxUsedWeights : number  = 0;
-            let numberNotNormalized : number  = 0;
-            let numInfluences : number  = matricesWeightsExtra === null ? 4 : 8;
+            let numberNotSorted: number = 0;
+            let missingWeights: number = 0;
+            let maxUsedWeights: number = 0;
+            let numberNotNormalized: number = 0;
+            let numInfluences: number = matricesWeightsExtra === null ? 4 : 8;
             var usedWeightCounts = new Array<number>();
             for (var a = 0; a <= numInfluences; a++) {
                 usedWeightCounts[a] = 0;
             }
-            const toleranceEpsilon : number = 0.001;
+            const toleranceEpsilon: number = 0.001;
 
             for (var a = 0; a < numWeights; a += 4) {
 
-                let lastWeight : number = matricesWeights[a];
+                let lastWeight: number = matricesWeights[a];
                 var t = lastWeight;
-                let usedWeights : number = t === 0 ? 0 : 1;
+                let usedWeights: number = t === 0 ? 0 : 1;
 
                 for (var b = 1; b < numInfluences; b++) {
                     var d = b < 4 ? matricesWeights[a + b] : matricesWeightsExtra[a + b - 4];
@@ -1746,10 +1746,10 @@ module BABYLON {
                     let tolerance = 0;
                     for (b = 0; b < numInfluences; b++) {
                         if (b < 4) {
-                            tolerance += Math.abs(matricesWeights[a + b] - (matricesWeights[a + b] * recip));
+                            tolerance += Math.abs(matricesWeights[a + b] - (matricesWeights[a + b] * recip));
                         }
                         else {
-                            tolerance += Math.abs(matricesWeightsExtra[a + b - 4] - (matricesWeightsExtra[a + b - 4] * recip));
+                            tolerance += Math.abs(matricesWeightsExtra[a + b - 4] - (matricesWeightsExtra[a + b - 4] * recip));
                         }
                     }
                     // arbitary epsilon value for dicdating not normalized
@@ -1761,7 +1761,7 @@ module BABYLON {
             let numBones: number = this.skeleton.bones.length;
             let matricesIndices = (<FloatArray>this.getVerticesData(VertexBuffer.MatricesIndicesKind));
             let matricesIndicesExtra = (<FloatArray>this.getVerticesData(VertexBuffer.MatricesIndicesExtraKind));
-            let numBadBoneIndices : number = 0;
+            let numBadBoneIndices: number = 0;
             for (var a = 0; a < numWeights; a++) {
                 for (var b = 0; b < numInfluences; b++) {
                     let index = b < 4 ? matricesIndices[b] : matricesIndicesExtra[b - 4];
@@ -1771,11 +1771,11 @@ module BABYLON {
 
             // log mesh stats
             var output = "Number of Weights = " + numWeights / 4 + "\nMaximum influences = " + maxUsedWeights +
-                         "\nMissing Weights = " + missingWeights + "\nNot Sorted = " + numberNotSorted +
-                         "\nNot Normalized = " + numberNotNormalized + "\nWeightCounts = [" + usedWeightCounts + "]" +
-                         "\nNumber of bones = " + numBones + "\nBad Bone Indices = " + numBadBoneIndices ;
+                "\nMissing Weights = " + missingWeights + "\nNot Sorted = " + numberNotSorted +
+                "\nNot Normalized = " + numberNotNormalized + "\nWeightCounts = [" + usedWeightCounts + "]" +
+                "\nNumber of bones = " + numBones + "\nBad Bone Indices = " + numBadBoneIndices;
 
-            return {skinned: true, valid: missingWeights === 0 && numberNotNormalized === 0 && numBadBoneIndices === 0, report: output};
+            return { skinned: true, valid: missingWeights === 0 && numberNotNormalized === 0 && numBadBoneIndices === 0, report: output };
         }
 
         /** @hidden */
@@ -1813,7 +1813,7 @@ module BABYLON {
                 this.delayLoadState = Engine.DELAYLOADSTATE_LOADED;
                 scene._removePendingData(this);
 
-            }, () => { }, scene.database, getBinaryData);
+            }, () => { }, scene.offlineProvider, getBinaryData);
             return this;
         }
 
@@ -2074,7 +2074,7 @@ module BABYLON {
                 }
             };
 
-            Tools.LoadImage(url, onload, () => { }, scene.database);
+            Tools.LoadImage(url, onload, () => { }, scene.offlineProvider);
             return this;
         }
 
@@ -2917,20 +2917,20 @@ module BABYLON {
             return mesh;
         }
 
-         /**
-          * Creates a ribbon mesh. Please consider using the same method from the MeshBuilder class instead
-          * @see http://doc.babylonjs.com/how_to/parametric_shapes
-          * @param name defines the name of the mesh to create
-          * @param pathArray is a required array of paths, what are each an array of successive Vector3. The pathArray parameter depicts the ribbon geometry.
-          * @param closeArray creates a seam between the first and the last paths of the path array (default is false)
-          * @param closePath creates a seam between the first and the last points of each path of the path array
-          * @param offset is taken in account only if the `pathArray` is containing a single path
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @param instance defines an instance of an existing Ribbon object to be updated with the passed `pathArray` parameter (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#ribbon)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a ribbon mesh. Please consider using the same method from the MeshBuilder class instead
+         * @see http://doc.babylonjs.com/how_to/parametric_shapes
+         * @param name defines the name of the mesh to create
+         * @param pathArray is a required array of paths, what are each an array of successive Vector3. The pathArray parameter depicts the ribbon geometry.
+         * @param closeArray creates a seam between the first and the last paths of the path array (default is false)
+         * @param closePath creates a seam between the first and the last points of each path of the path array
+         * @param offset is taken in account only if the `pathArray` is containing a single path
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @param instance defines an instance of an existing Ribbon object to be updated with the passed `pathArray` parameter (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#ribbon)
+         * @returns a new Mesh
+         */
         public static CreateRibbon(name: string, pathArray: Vector3[][], closeArray: boolean = false, closePath: boolean, offset: number, scene?: Scene, updatable: boolean = false, sideOrientation?: number, instance?: Mesh): Mesh {
             return MeshBuilder.CreateRibbon(name, {
                 pathArray: pathArray,
@@ -2964,15 +2964,15 @@ module BABYLON {
             return MeshBuilder.CreateDisc(name, options, scene);
         }
 
-         /**
-          * Creates a box mesh. Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param size sets the size (float) of each box side (default 1)
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a box mesh. Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param size sets the size (float) of each box side (default 1)
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @returns a new Mesh
+         */
         public static CreateBox(name: string, size: number, scene: Nullable<Scene> = null, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 size: size,
@@ -3006,19 +3006,19 @@ module BABYLON {
             return MeshBuilder.CreateSphere(name, options, scene);
         }
 
-         /**
-          * Creates a cylinder or a cone mesh. Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param height sets the height size (float) of the cylinder/cone (float, default 2)
-          * @param diameterTop set the top cap diameter (floats, default 1)
-          * @param diameterBottom set the bottom cap diameter (floats, default 1). This value can't be zero
-          * @param tessellation sets the number of cylinder sides (positive integer, default 24). Set it to 3 to get a prism for instance
-          * @param subdivisions sets the number of rings along the cylinder height (positive integer, default 1)
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a cylinder or a cone mesh. Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param height sets the height size (float) of the cylinder/cone (float, default 2)
+         * @param diameterTop set the top cap diameter (floats, default 1)
+         * @param diameterBottom set the bottom cap diameter (floats, default 1). This value can't be zero
+         * @param tessellation sets the number of cylinder sides (positive integer, default 24). Set it to 3 to get a prism for instance
+         * @param subdivisions sets the number of rings along the cylinder height (positive integer, default 1)
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @returns a new Mesh
+         */
         public static CreateCylinder(name: string, height: number, diameterTop: number, diameterBottom: number, tessellation: number, subdivisions: any, scene?: Scene, updatable?: any, sideOrientation?: number): Mesh {
             if (scene === undefined || !(scene instanceof Scene)) {
                 if (scene !== undefined) {
@@ -3066,20 +3066,20 @@ module BABYLON {
             return MeshBuilder.CreateTorus(name, options, scene);
         }
 
-         /**
-          * Creates a torus knot mesh. Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param radius sets the global radius size (float) of the torus knot (default 2)
-          * @param tube sets the diameter size of the tube of the torus (float, default 0.5)
-          * @param radialSegments sets the number of sides on each tube segments (positive integer, default 32)
-          * @param tubularSegments sets the number of tubes to decompose the knot into (positive integer, default 32)
-          * @param p the number of windings on X axis (positive integers, default 2)
-          * @param q the number of windings on Y axis (positive integers, default 3)
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a torus knot mesh. Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param radius sets the global radius size (float) of the torus knot (default 2)
+         * @param tube sets the diameter size of the tube of the torus (float, default 0.5)
+         * @param radialSegments sets the number of sides on each tube segments (positive integer, default 32)
+         * @param tubularSegments sets the number of tubes to decompose the knot into (positive integer, default 32)
+         * @param p the number of windings on X axis (positive integers, default 2)
+         * @param q the number of windings on Y axis (positive integers, default 3)
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @returns a new Mesh
+         */
         public static CreateTorusKnot(name: string, radius: number, tube: number, radialSegments: number, tubularSegments: number, p: number, q: number, scene?: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 radius: radius,
@@ -3095,15 +3095,15 @@ module BABYLON {
             return MeshBuilder.CreateTorusKnot(name, options, scene);
         }
 
-         /**
-          * Creates a line mesh. Please consider using the same method from the MeshBuilder class instead.
-          * @param name defines the name of the mesh to create
-          * @param points is an array successive Vector3
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param instance is an instance of an existing LineMesh object to be updated with the passed `points` parameter (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#lines-and-dashedlines).
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a line mesh. Please consider using the same method from the MeshBuilder class instead.
+         * @param name defines the name of the mesh to create
+         * @param points is an array successive Vector3
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param instance is an instance of an existing LineMesh object to be updated with the passed `points` parameter (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#lines-and-dashedlines).
+         * @returns a new Mesh
+         */
         public static CreateLines(name: string, points: Vector3[], scene: Nullable<Scene> = null, updatable: boolean = false, instance: Nullable<LinesMesh> = null): LinesMesh {
             var options = {
                 points: points,
@@ -3113,18 +3113,18 @@ module BABYLON {
             return MeshBuilder.CreateLines(name, options, scene);
         }
 
-         /**
-          * Creates a dashed line mesh. Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param points is an array successive Vector3
-          * @param dashSize is the size of the dashes relatively the dash number (positive float, default 3)
-          * @param gapSize is the size of the gap between two successive dashes relatively the dash number (positive float, default 1)
-          * @param dashNb is the intended total number of dashes (positive integer, default 200)
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param instance is an instance of an existing LineMesh object to be updated with the passed `points` parameter (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#lines-and-dashedlines)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a dashed line mesh. Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param points is an array successive Vector3
+         * @param dashSize is the size of the dashes relatively the dash number (positive float, default 3)
+         * @param gapSize is the size of the gap between two successive dashes relatively the dash number (positive float, default 1)
+         * @param dashNb is the intended total number of dashes (positive integer, default 200)
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param instance is an instance of an existing LineMesh object to be updated with the passed `points` parameter (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#lines-and-dashedlines)
+         * @returns a new Mesh
+         */
         public static CreateDashedLines(name: string, points: Vector3[], dashSize: number, gapSize: number, dashNb: number, scene: Nullable<Scene> = null, updatable?: boolean, instance?: LinesMesh): LinesMesh {
             var options = {
                 points: points,
@@ -3147,17 +3147,17 @@ module BABYLON {
          * Remember you can only change the shape positions, not their number when updating a polygon.
          */
 
-         /**
-          * Creates a polygon mesh.Please consider using the same method from the MeshBuilder class instead
-          * @see http://doc.babylonjs.com/how_to/parametric_shapes#non-regular-polygon
-          * @param name defines the name of the mesh to create
-          * @param shape is a required array of successive Vector3 representing the corners of the polygon in th XoZ plane, that is y = 0 for all vectors
-          * @param scene defines the hosting scene
-          * @param holes is a required array of arrays of successive Vector3 used to defines holes in the polygon
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a polygon mesh.Please consider using the same method from the MeshBuilder class instead
+         * @see http://doc.babylonjs.com/how_to/parametric_shapes#non-regular-polygon
+         * @param name defines the name of the mesh to create
+         * @param shape is a required array of successive Vector3 representing the corners of the polygon in th XoZ plane, that is y = 0 for all vectors
+         * @param scene defines the hosting scene
+         * @param holes is a required array of arrays of successive Vector3 used to defines holes in the polygon
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @returns a new Mesh
+         */
         public static CreatePolygon(name: string, shape: Vector3[], scene: Scene, holes?: Vector3[][], updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 shape: shape,
@@ -3168,18 +3168,18 @@ module BABYLON {
             return MeshBuilder.CreatePolygon(name, options, scene);
         }
 
-         /**
-          * Creates an extruded polygon mesh, with depth in the Y direction. Please consider using the same method from the MeshBuilder class instead.
-          * @see http://doc.babylonjs.com/how_to/parametric_shapes#extruded-non-regular-polygon
-          * @param name defines the name of the mesh to create
-          * @param shape is a required array of successive Vector3 representing the corners of the polygon in th XoZ plane, that is y = 0 for all vectors
-          * @param depth defines the height of extrusion
-          * @param scene defines the hosting scene
-          * @param holes is a required array of arrays of successive Vector3 used to defines holes in the polygon
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates an extruded polygon mesh, with depth in the Y direction. Please consider using the same method from the MeshBuilder class instead.
+         * @see http://doc.babylonjs.com/how_to/parametric_shapes#extruded-non-regular-polygon
+         * @param name defines the name of the mesh to create
+         * @param shape is a required array of successive Vector3 representing the corners of the polygon in th XoZ plane, that is y = 0 for all vectors
+         * @param depth defines the height of extrusion
+         * @param scene defines the hosting scene
+         * @param holes is a required array of arrays of successive Vector3 used to defines holes in the polygon
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @returns a new Mesh
+         */
         public static ExtrudePolygon(name: string, shape: Vector3[], depth: number, scene: Scene, holes?: Vector3[][], updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 shape: shape,
@@ -3191,23 +3191,23 @@ module BABYLON {
             return MeshBuilder.ExtrudePolygon(name, options, scene);
         }
 
-         /**
-          * Creates an extruded shape mesh.
-          * The extrusion is a parametric shape. It has no predefined shape. Its final shape will depend on the input parameters. Please consider using the same method from the MeshBuilder class instead
-          * @see http://doc.babylonjs.com/how_to/parametric_shapes
-          * @see http://doc.babylonjs.com/how_to/parametric_shapes#extruded-shapes
-          * @param name defines the name of the mesh to create
-          * @param shape is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be extruded along the Z axis
-          * @param path is a required array of successive Vector3. This is the axis curve the shape is extruded along
-          * @param scale is the value to scale the shape
-          * @param rotation is the angle value to rotate the shape each step (each path point), from the former step (so rotation added each step) along the curve
-          * @param cap sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @param instance is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#extruded-shape)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates an extruded shape mesh.
+         * The extrusion is a parametric shape. It has no predefined shape. Its final shape will depend on the input parameters. Please consider using the same method from the MeshBuilder class instead
+         * @see http://doc.babylonjs.com/how_to/parametric_shapes
+         * @see http://doc.babylonjs.com/how_to/parametric_shapes#extruded-shapes
+         * @param name defines the name of the mesh to create
+         * @param shape is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be extruded along the Z axis
+         * @param path is a required array of successive Vector3. This is the axis curve the shape is extruded along
+         * @param scale is the value to scale the shape
+         * @param rotation is the angle value to rotate the shape each step (each path point), from the former step (so rotation added each step) along the curve
+         * @param cap sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @param instance is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters (http://doc.babylonjs.com/how_to/How_to_dynamically_morph_a_mesh#extruded-shape)
+         * @returns a new Mesh
+         */
         public static ExtrudeShape(name: string, shape: Vector3[], path: Vector3[], scale: number, rotation: number, cap: number, scene: Nullable<Scene> = null, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
             var options = {
                 shape: shape,
@@ -3223,26 +3223,26 @@ module BABYLON {
             return MeshBuilder.ExtrudeShape(name, options, scene);
         }
 
-         /**
-          * Creates an custom extruded shape mesh.
-          * The custom extrusion is a parametric shape.
-          * It has no predefined shape. Its final shape will depend on the input parameters.
-          * Please consider using the same method from the MeshBuilder class instead
-          * @see http://doc.babylonjs.com/how_to/parametric_shapes#extruded-shapes
-          * @param name defines the name of the mesh to create
-          * @param shape is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be extruded along the Z axis
-          * @param path is a required array of successive Vector3. This is the axis curve the shape is extruded along
-          * @param scaleFunction is a custom Javascript function called on each path point
-          * @param rotationFunction is a custom Javascript function called on each path point
-          * @param ribbonCloseArray forces the extrusion underlying ribbon to close all the paths in its `pathArray`
-          * @param ribbonClosePath forces the extrusion underlying ribbon to close its `pathArray`
-          * @param cap sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @param instance is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters (http://doc.babylonjs.com/how_to/how_to_dynamically_morph_a_mesh#extruded-shape)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates an custom extruded shape mesh.
+         * The custom extrusion is a parametric shape.
+         * It has no predefined shape. Its final shape will depend on the input parameters.
+         * Please consider using the same method from the MeshBuilder class instead
+         * @see http://doc.babylonjs.com/how_to/parametric_shapes#extruded-shapes
+         * @param name defines the name of the mesh to create
+         * @param shape is a required array of successive Vector3. This array depicts the shape to be extruded in its local space : the shape must be designed in the xOy plane and will be extruded along the Z axis
+         * @param path is a required array of successive Vector3. This is the axis curve the shape is extruded along
+         * @param scaleFunction is a custom Javascript function called on each path point
+         * @param rotationFunction is a custom Javascript function called on each path point
+         * @param ribbonCloseArray forces the extrusion underlying ribbon to close all the paths in its `pathArray`
+         * @param ribbonClosePath forces the extrusion underlying ribbon to close its `pathArray`
+         * @param cap sets the way the extruded shape is capped. Possible values : BABYLON.Mesh.NO_CAP (default), BABYLON.Mesh.CAP_START, BABYLON.Mesh.CAP_END, BABYLON.Mesh.CAP_ALL
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @param instance is an instance of an existing ExtrudedShape object to be updated with the passed `shape`, `path`, `scale` or `rotation` parameters (http://doc.babylonjs.com/how_to/how_to_dynamically_morph_a_mesh#extruded-shape)
+         * @returns a new Mesh
+         */
         public static ExtrudeShapeCustom(name: string, shape: Vector3[], path: Vector3[], scaleFunction: Function, rotationFunction: Function, ribbonCloseArray: boolean, ribbonClosePath: boolean, cap: number, scene: Scene, updatable?: boolean, sideOrientation?: number, instance?: Mesh): Mesh {
             var options = {
                 shape: shape,
@@ -3260,19 +3260,19 @@ module BABYLON {
             return MeshBuilder.ExtrudeShapeCustom(name, options, scene);
         }
 
-         /**
-          * Creates lathe mesh.
-          * The lathe is a shape with a symetry axis : a 2D model shape is rotated around this axis to design the lathe.
-          * Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param shape is a required array of successive Vector3. This array depicts the shape to be rotated in its local space : the shape must be designed in the xOy plane and will be rotated around the Y axis. It's usually a 2D shape, so the Vector3 z coordinates are often set to zero
-          * @param radius is the radius value of the lathe
-          * @param tessellation is the side number of the lathe.
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates lathe mesh.
+         * The lathe is a shape with a symetry axis : a 2D model shape is rotated around this axis to design the lathe.
+         * Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param shape is a required array of successive Vector3. This array depicts the shape to be rotated in its local space : the shape must be designed in the xOy plane and will be rotated around the Y axis. It's usually a 2D shape, so the Vector3 z coordinates are often set to zero
+         * @param radius is the radius value of the lathe
+         * @param tessellation is the side number of the lathe.
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @returns a new Mesh
+         */
         public static CreateLathe(name: string, shape: Vector3[], radius: number, tessellation: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 shape: shape,
@@ -3285,15 +3285,15 @@ module BABYLON {
             return MeshBuilder.CreateLathe(name, options, scene);
         }
 
-         /**
-          * Creates a plane mesh. Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param size sets the size (float) of both sides of the plane at once (default 1)
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a plane mesh. Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param size sets the size (float) of both sides of the plane at once (default 1)
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param sideOrientation defines the mesh side orientation (http://doc.babylonjs.com/babylon101/discover_basic_elements#side-orientation)
+         * @returns a new Mesh
+         */
         public static CreatePlane(name: string, size: number, scene: Scene, updatable?: boolean, sideOrientation?: number): Mesh {
             var options = {
                 size: size,
@@ -3306,17 +3306,17 @@ module BABYLON {
             return MeshBuilder.CreatePlane(name, options, scene);
         }
 
-         /**
-          * Creates a ground mesh.
-          * Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param width set the width of the ground
-          * @param height set the height of the ground
-          * @param subdivisions sets the number of subdivisions per side
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a ground mesh.
+         * Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param width set the width of the ground
+         * @param height set the height of the ground
+         * @param subdivisions sets the number of subdivisions per side
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @returns a new Mesh
+         */
         public static CreateGround(name: string, width: number, height: number, subdivisions: number, scene?: Scene, updatable?: boolean): Mesh {
             var options = {
                 width: width,
@@ -3328,20 +3328,20 @@ module BABYLON {
             return MeshBuilder.CreateGround(name, options, scene);
         }
 
-         /**
-          * Creates a tiled ground mesh.
-          * Please consider using the same method from the MeshBuilder class instead
-          * @param name defines the name of the mesh to create
-          * @param xmin set the ground minimum X coordinate
-          * @param zmin set the ground minimum Y coordinate
-          * @param xmax set the ground maximum X coordinate
-          * @param zmax set the ground maximum Z coordinate
-          * @param subdivisions is an object `{w: positive integer, h: positive integer}` (default `{w: 6, h: 6}`). `w` and `h` are the numbers of subdivisions on the ground width and height. Each subdivision is called a tile
-          * @param precision is an object `{w: positive integer, h: positive integer}` (default `{w: 2, h: 2}`). `w` and `h` are the numbers of subdivisions on the ground width and height of each tile
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a tiled ground mesh.
+         * Please consider using the same method from the MeshBuilder class instead
+         * @param name defines the name of the mesh to create
+         * @param xmin set the ground minimum X coordinate
+         * @param zmin set the ground minimum Y coordinate
+         * @param xmax set the ground maximum X coordinate
+         * @param zmax set the ground maximum Z coordinate
+         * @param subdivisions is an object `{w: positive integer, h: positive integer}` (default `{w: 6, h: 6}`). `w` and `h` are the numbers of subdivisions on the ground width and height. Each subdivision is called a tile
+         * @param precision is an object `{w: positive integer, h: positive integer}` (default `{w: 2, h: 2}`). `w` and `h` are the numbers of subdivisions on the ground width and height of each tile
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @returns a new Mesh
+         */
         public static CreateTiledGround(name: string, xmin: number, zmin: number, xmax: number, zmax: number, subdivisions: { w: number; h: number; }, precision: { w: number; h: number; }, scene: Scene, updatable?: boolean): Mesh {
             var options = {
                 xmin: xmin,
@@ -3356,23 +3356,23 @@ module BABYLON {
             return MeshBuilder.CreateTiledGround(name, options, scene);
         }
 
-         /**
-          * Creates a ground mesh from a height map.
-          * Please consider using the same method from the MeshBuilder class instead
-          * @see http://doc.babylonjs.com/babylon101/height_map
-          * @param name defines the name of the mesh to create
-          * @param url sets the URL of the height map image resource
-          * @param width set the ground width size
-          * @param height set the ground height size
-          * @param subdivisions sets the number of subdivision per side
-          * @param minHeight is the minimum altitude on the ground
-          * @param maxHeight is the maximum altitude on the ground
-          * @param scene defines the hosting scene
-          * @param updatable defines if the mesh must be flagged as updatable
-          * @param onReady  is a callback function that will be called  once the mesh is built (the height map download can last some time)
-          * @param alphaFilter will filter any data where the alpha channel is below this value, defaults 0 (all data visible)
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a ground mesh from a height map.
+         * Please consider using the same method from the MeshBuilder class instead
+         * @see http://doc.babylonjs.com/babylon101/height_map
+         * @param name defines the name of the mesh to create
+         * @param url sets the URL of the height map image resource
+         * @param width set the ground width size
+         * @param height set the ground height size
+         * @param subdivisions sets the number of subdivision per side
+         * @param minHeight is the minimum altitude on the ground
+         * @param maxHeight is the maximum altitude on the ground
+         * @param scene defines the hosting scene
+         * @param updatable defines if the mesh must be flagged as updatable
+         * @param onReady  is a callback function that will be called  once the mesh is built (the height map download can last some time)
+         * @param alphaFilter will filter any data where the alpha channel is below this value, defaults 0 (all data visible)
+         * @returns a new Mesh
+         */
         public static CreateGroundFromHeightMap(name: string, url: string, width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, scene: Scene, updatable?: boolean, onReady?: (mesh: GroundMesh) => void, alphaFilter?: number): GroundMesh {
             var options = {
                 width: width,
@@ -3463,18 +3463,18 @@ module BABYLON {
             return MeshBuilder.CreateIcoSphere(name, options, scene);
         }
 
-         /**
-          * Creates a decal mesh.
-          * Please consider using the same method from the MeshBuilder class instead.
-          * A decal is a mesh usually applied as a model onto the surface of another mesh
-          * @param name  defines the name of the mesh
-          * @param sourceMesh defines the mesh receiving the decal
-          * @param position sets the position of the decal in world coordinates
-          * @param normal sets the normal of the mesh where the decal is applied onto in world coordinates
-          * @param size sets the decal scaling
-          * @param angle sets the angle to rotate the decal
-          * @returns a new Mesh
-          */
+        /**
+         * Creates a decal mesh.
+         * Please consider using the same method from the MeshBuilder class instead.
+         * A decal is a mesh usually applied as a model onto the surface of another mesh
+         * @param name  defines the name of the mesh
+         * @param sourceMesh defines the mesh receiving the decal
+         * @param position sets the position of the decal in world coordinates
+         * @param normal sets the normal of the mesh where the decal is applied onto in world coordinates
+         * @param size sets the decal scaling
+         * @param angle sets the angle to rotate the decal
+         * @returns a new Mesh
+         */
         public static CreateDecal(name: string, sourceMesh: AbstractMesh, position: Vector3, normal: Vector3, size: Vector3, angle: number): Mesh {
             var options = {
                 position: position,
@@ -3645,11 +3645,11 @@ module BABYLON {
 
         // Tools
 
-         /**
-          * Returns an object containing a min and max Vector3 which are the minimum and maximum vectors of each mesh bounding box from the passed array, in the world coordinates
-          * @param meshes defines the list of meshes to scan
-          * @returns an object `{min:` Vector3`, max:` Vector3`}`
-          */
+        /**
+         * Returns an object containing a min and max Vector3 which are the minimum and maximum vectors of each mesh bounding box from the passed array, in the world coordinates
+         * @param meshes defines the list of meshes to scan
+         * @returns an object `{min:` Vector3`, max:` Vector3`}`
+         */
         public static MinMax(meshes: AbstractMesh[]): { min: Vector3; max: Vector3 } {
             var minVector: Nullable<Vector3> = null;
             var maxVector: Nullable<Vector3> = null;
@@ -3680,11 +3680,11 @@ module BABYLON {
             };
         }
 
-         /**
-          * Returns the center of the `{min:` Vector3`, max:` Vector3`}` or the center of MinMax vector3 computed from a mesh array
-          * @param meshesOrMinMaxVector could be an array of meshes or a `{min:` Vector3`, max:` Vector3`}` object
-          * @returns a vector3
-          */
+        /**
+         * Returns the center of the `{min:` Vector3`, max:` Vector3`}` or the center of MinMax vector3 computed from a mesh array
+         * @param meshesOrMinMaxVector could be an array of meshes or a `{min:` Vector3`, max:` Vector3`}` object
+         * @returns a vector3
+         */
         public static Center(meshesOrMinMaxVector: { min: Vector3; max: Vector3 } | AbstractMesh[]): Vector3 {
             var minMaxVector = (meshesOrMinMaxVector instanceof Array) ? Mesh.MinMax(meshesOrMinMaxVector) : meshesOrMinMaxVector;
             return Vector3.Center(minMaxVector.min, minMaxVector.max);

+ 5 - 5
src/Mesh/babylon.meshBuilder.ts

@@ -204,7 +204,7 @@ module BABYLON {
                 instance.updateVerticesData(VertexBuffer.PositionKind, positions, false, false);
                 if (options.colors) {
                     var colors = <FloatArray>instance.getVerticesData(VertexBuffer.ColorKind);
-                    for (var c = 0, colorIndex = 0; c < options.colors.length; c++, colorIndex += 4) {
+                    for (var c = 0, colorIndex = 0; c < options.colors.length; c++ , colorIndex += 4) {
                         const color = options.colors[c];
                         colors[colorIndex] = color.r;
                         colors[colorIndex + 1] = color.g;
@@ -635,7 +635,7 @@ module BABYLON {
             var shape = options.shape;
             var radius = options.radius || 1;
             var tessellation = options.tessellation || 64;
-        var clip = options.clip || 0;
+            var clip = options.clip || 0;
             var updatable = options.updatable;
             var sideOrientation = MeshBuilder.updateSideOrientation(options.sideOrientation);
             var cap = options.cap || Mesh.NO_CAP;
@@ -846,7 +846,7 @@ module BABYLON {
                 ground._setReady(true);
             };
 
-            Tools.LoadImage(url, onload, () => { }, scene.database);
+            Tools.LoadImage(url, onload, () => { }, scene.offlineProvider);
 
             return ground;
         }
@@ -1017,7 +1017,7 @@ module BABYLON {
             if (instance) { // tube update
                 let storage = instance._creationDataStorage!;
                 var arc = options.arc || storage.arc;
-                path3D =  storage.path3D.update(path);
+                path3D = storage.path3D.update(path);
                 pathArray = tubePathArray(path, path3D, storage.pathArray, radius, storage.tessellation, radiusFunction, storage.cap, arc);
                 instance = MeshBuilder.CreateRibbon("", { pathArray: pathArray, instance: instance });
                 // Update mode, no need to recreate the storage.
@@ -1382,7 +1382,7 @@ module BABYLON {
             var pathArray;
             if (instance) { // instance update
                 let storage = instance._creationDataStorage!;
-                path3D =  storage.path3D.update(curve);
+                path3D = storage.path3D.update(curve);
                 pathArray = extrusionPathArray(shape, curve, storage.path3D, storage.pathArray, scale, rotation, scaleFunction, rotateFunction, storage.cap, custom);
                 instance = Mesh.CreateRibbon("", pathArray, false, false, 0, scene || undefined, false, 0, instance);
 

+ 41 - 0
src/Offline/babylon.IOfflineProvider.ts

@@ -0,0 +1,41 @@
+module BABYLON {
+    /**
+     * Class used to enable access to offline support
+     * @see http://doc.babylonjs.com/how_to/caching_resources_in_indexeddb
+     */
+    export interface IOfflineProvider {
+        /**
+         * Gets a boolean indicating if scene must be saved in the database
+         */
+        enableSceneOffline: boolean;
+
+        /**
+         * Gets a boolean indicating if textures must be saved in the database
+         */
+        enableTexturesOffline: boolean;
+
+        /**
+         * Open the offline support and make it available
+         * @param successCallback defines the callback to call on success
+         * @param errorCallback defines the callback to call on error
+         */
+        open(successCallback: () => void, errorCallback: () => void): void;
+
+        /**
+         * Loads an image from the offline support
+         * @param url defines the url to load from
+         * @param image defines the target DOM image
+         */
+        loadImage(url: string, image: HTMLImageElement): void;
+
+        /**
+         * Loads a file from offline support
+         * @param url defines the URL to load from
+         * @param sceneLoaded defines a callback to call on success
+         * @param progressCallBack defines a callback to call when progress changed
+         * @param errorCallback defines a callback to call on error
+         * @param useArrayBuffer defines a boolean to use array buffer instead of text string
+         */
+        loadFile(url: string, sceneLoaded: (data: any) => void, progressCallBack?: (data: any) => void, errorCallback?: () => void, useArrayBuffer?: boolean): void;
+    }
+}

+ 86 - 80
src/Tools/babylon.database.ts

@@ -1,27 +1,33 @@
 module BABYLON {
+
+    // Sets the default offline provider to Babylon.js
+    Engine.OfflineProviderFactory = (urlToScene: string, callbackManifestChecked: (checked: boolean) => any, disableManifestCheck = false) => { return new Database(urlToScene, callbackManifestChecked, disableManifestCheck); };
+
     /**
      * Class used to enable access to IndexedDB
-     * @see @https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
+     * @see http://doc.babylonjs.com/how_to/caching_resources_in_indexeddb
      */
-    export class Database {
-        private callbackManifestChecked: (check: boolean) => any;
-        private currentSceneUrl: string;
-        private db: Nullable<IDBDatabase>;
+    export class Database implements IOfflineProvider {
+        private _callbackManifestChecked: (check: boolean) => any;
+        private _currentSceneUrl: string;
+        private _db: Nullable<IDBDatabase>;
         private _enableSceneOffline: boolean;
         private _enableTexturesOffline: boolean;
-        private manifestVersionFound: number;
-        private mustUpdateRessources: boolean;
-        private hasReachedQuota: boolean;
-        private isSupported: boolean;
+        private _manifestVersionFound: number;
+        private _mustUpdateRessources: boolean;
+        private _hasReachedQuota: boolean;
+        private _isSupported: boolean;
 
         // Handling various flavors of prefixed version of IndexedDB
-        private idbFactory = <IDBFactory>(window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
+        private _idbFactory = <IDBFactory>(window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
 
         /** Gets a boolean indicating if the user agent supports blob storage (this value will be updated after creating the first Database object) */
-        static IsUASupportingBlobStorage = true;
+        private static IsUASupportingBlobStorage = true;
 
-        /** Gets a boolean indicating if Database storate is enabled */
-        static IDBStorageEnabled = true;
+        /**
+         * Gets a boolean indicating if Database storate is enabled (off by default)
+         */
+        static IDBStorageEnabled = false;
 
         /**
          * Gets a boolean indicating if scene must be saved in the database
@@ -44,24 +50,24 @@ module BABYLON {
          * @param disableManifestCheck defines a boolean indicating that we want to skip the manifest validation (it will be considered validated and up to date)
          */
         constructor(urlToScene: string, callbackManifestChecked: (checked: boolean) => any, disableManifestCheck = false) {
-            this.callbackManifestChecked = callbackManifestChecked;
-            this.currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
-            this.db = null;
+            this._callbackManifestChecked = callbackManifestChecked;
+            this._currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
+            this._db = null;
             this._enableSceneOffline = false;
             this._enableTexturesOffline = false;
-            this.manifestVersionFound = 0;
-            this.mustUpdateRessources = false;
-            this.hasReachedQuota = false;
+            this._manifestVersionFound = 0;
+            this._mustUpdateRessources = false;
+            this._hasReachedQuota = false;
 
             if (!Database.IDBStorageEnabled) {
-                this.callbackManifestChecked(true);
+                this._callbackManifestChecked(true);
             } else {
                 if (disableManifestCheck) {
                     this._enableSceneOffline = true;
                     this._enableTexturesOffline = true;
-                    this.manifestVersionFound = 1;
+                    this._manifestVersionFound = 1;
                     Tools.SetImmediate(() => {
-                        this.callbackManifestChecked(true);
+                        this._callbackManifestChecked(true);
                     });
                 }
                 else {
@@ -92,11 +98,11 @@ module BABYLON {
             var noManifestFile = () => {
                 this._enableSceneOffline = false;
                 this._enableTexturesOffline = false;
-                this.callbackManifestChecked(false);
+                this._callbackManifestChecked(false);
             };
 
             var timeStampUsed = false;
-            var manifestURL = this.currentSceneUrl + ".manifest";
+            var manifestURL = this._currentSceneUrl + ".manifest";
 
             var xhr: XMLHttpRequest = new XMLHttpRequest();
 
@@ -112,12 +118,12 @@ module BABYLON {
                     try {
                         var manifestFile = JSON.parse(xhr.response);
                         this._enableSceneOffline = manifestFile.enableSceneOffline;
-                        this._enableTexturesOffline = manifestFile.enableTexturesOffline;
+                        this._enableTexturesOffline = manifestFile.enableTexturesOffline && Database.IsUASupportingBlobStorage;
                         if (manifestFile.version && !isNaN(parseInt(manifestFile.version))) {
-                            this.manifestVersionFound = manifestFile.version;
+                            this._manifestVersionFound = manifestFile.version;
                         }
-                        if (this.callbackManifestChecked) {
-                            this.callbackManifestChecked(true);
+                        if (this._callbackManifestChecked) {
+                            this._callbackManifestChecked(true);
                         }
                     }
                     catch (ex) {
@@ -134,7 +140,7 @@ module BABYLON {
                     timeStampUsed = false;
                     // Let's retry without the timeStamp
                     // It could fail when coupled with HTML5 Offline API
-                    var retryManifestURL = this.currentSceneUrl + ".manifest";
+                    var retryManifestURL = this._currentSceneUrl + ".manifest";
                     xhr.open("GET", retryManifestURL, true);
                     xhr.send();
                 }
@@ -148,7 +154,7 @@ module BABYLON {
             }
             catch (ex) {
                 Tools.Error("Error on XHR send request.");
-                this.callbackManifestChecked(false);
+                this._callbackManifestChecked(false);
             }
         }
 
@@ -157,24 +163,24 @@ module BABYLON {
          * @param successCallback defines the callback to call on success
          * @param errorCallback defines the callback to call on error
          */
-        public openAsync(successCallback: () => void, errorCallback: () => void) {
+        public open(successCallback: () => void, errorCallback: () => void): void {
             let handleError = () => {
-                this.isSupported = false;
+                this._isSupported = false;
                 if (errorCallback) { errorCallback(); }
             };
 
-            if (!this.idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
+            if (!this._idbFactory || !(this._enableSceneOffline || this._enableTexturesOffline)) {
                 // Your browser doesn't support IndexedDB
-                this.isSupported = false;
+                this._isSupported = false;
                 if (errorCallback) { errorCallback(); }
             }
             else {
                 // If the DB hasn't been opened or created yet
-                if (!this.db) {
-                    this.hasReachedQuota = false;
-                    this.isSupported = true;
+                if (!this._db) {
+                    this._hasReachedQuota = false;
+                    this._isSupported = true;
 
-                    var request: IDBOpenDBRequest = this.idbFactory.open("babylonjs", 1);
+                    var request: IDBOpenDBRequest = this._idbFactory.open("babylonjs", 1);
 
                     // Could occur if user is blocking the quota for the DB and/or doesn't grant access to IndexedDB
                     request.onerror = (event) => {
@@ -189,18 +195,18 @@ module BABYLON {
 
                     // DB has been opened successfully
                     request.onsuccess = (event) => {
-                        this.db = request.result;
+                        this._db = request.result;
                         successCallback();
                     };
 
                     // Initialization of the DB. Creating Scenes & Textures stores
                     request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
-                        this.db = (<any>(event.target)).result;
-                        if (this.db) {
+                        this._db = (<any>(event.target)).result;
+                        if (this._db) {
                             try {
-                                this.db.createObjectStore("scenes", { keyPath: "sceneUrl" });
-                                this.db.createObjectStore("versions", { keyPath: "sceneUrl" });
-                                this.db.createObjectStore("textures", { keyPath: "textureUrl" });
+                                this._db.createObjectStore("scenes", { keyPath: "sceneUrl" });
+                                this._db.createObjectStore("versions", { keyPath: "sceneUrl" });
+                                this._db.createObjectStore("textures", { keyPath: "textureUrl" });
                             }
                             catch (ex) {
                                 Tools.Error("Error while creating object stores. Exception: " + ex.message);
@@ -221,11 +227,11 @@ module BABYLON {
          * @param url defines the url to load from
          * @param image defines the target DOM image
          */
-        public loadImageFromDB(url: string, image: HTMLImageElement) {
+        public loadImage(url: string, image: HTMLImageElement) {
             var completeURL = Database._ReturnFullUrlLocation(url);
 
             var saveAndLoadImage = () => {
-                if (!this.hasReachedQuota && this.db !== null) {
+                if (!this._hasReachedQuota && this._db !== null) {
                     // the texture is not yet in the DB, let's try to save it
                     this._saveImageIntoDBAsync(completeURL, image);
                 }
@@ -236,7 +242,7 @@ module BABYLON {
                 }
             };
 
-            if (!this.mustUpdateRessources) {
+            if (!this._mustUpdateRessources) {
                 this._loadImageFromDBAsync(completeURL, image, saveAndLoadImage);
             }
             // First time we're download the images or update requested in the manifest file by a version change
@@ -246,9 +252,9 @@ module BABYLON {
         }
 
         private _loadImageFromDBAsync(url: string, image: HTMLImageElement, notInDBCallback: () => any) {
-            if (this.isSupported && this.db !== null) {
+            if (this._isSupported && this._db !== null) {
                 var texture: any;
-                var transaction: IDBTransaction = this.db.transaction(["textures"]);
+                var transaction: IDBTransaction = this._db.transaction(["textures"]);
 
                 transaction.onabort = (event) => {
                     image.src = url;
@@ -288,7 +294,7 @@ module BABYLON {
         }
 
         private _saveImageIntoDBAsync(url: string, image: HTMLImageElement) {
-            if (this.isSupported) {
+            if (this._isSupported) {
                 // In case of error (type not supported or quota exceeded), we're at least sending back XHR data to allow texture loading later on
                 var generateBlobUrl = () => {
                     var blobTextureURL;
@@ -317,11 +323,11 @@ module BABYLON {
                     xhr.responseType = "blob";
 
                     xhr.addEventListener("load", () => {
-                        if (xhr.status === 200 && this.db) {
+                        if (xhr.status === 200 && this._db) {
                             // Blob as response (XHR2)
                             blob = xhr.response;
 
-                            var transaction = this.db.transaction(["textures"], "readwrite");
+                            var transaction = this._db.transaction(["textures"], "readwrite");
 
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = (event) => {
@@ -330,7 +336,7 @@ module BABYLON {
                                     let srcElement = <any>(event.srcElement || event.target);
                                     var error = srcElement.error;
                                     if (error && error.name === "QuotaExceededError") {
-                                        this.hasReachedQuota = true;
+                                        this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -356,6 +362,7 @@ module BABYLON {
                                 // "DataCloneError" generated by Chrome when you try to inject blob into IndexedDB
                                 if (ex.code === 25) {
                                     Database.IsUASupportingBlobStorage = false;
+                                    this._enableTexturesOffline = false;
                                 }
                                 image.src = url;
                             }
@@ -391,16 +398,16 @@ module BABYLON {
         }
 
         private _loadVersionFromDBAsync(url: string, callback: (version: number) => void, updateInDBCallback: () => void) {
-            if (this.isSupported && this.db) {
+            if (this._isSupported && this._db) {
                 var version: any;
                 try {
-                    var transaction = this.db.transaction(["versions"]);
+                    var transaction = this._db.transaction(["versions"]);
 
                     transaction.oncomplete = (event) => {
                         if (version) {
                             // If the version in the JSON file is different from the version in DB
-                            if (this.manifestVersionFound !== version.data) {
-                                this.mustUpdateRessources = true;
+                            if (this._manifestVersionFound !== version.data) {
+                                this._mustUpdateRessources = true;
                                 updateInDBCallback();
                             }
                             else {
@@ -409,7 +416,7 @@ module BABYLON {
                         }
                         // version was not found in DB
                         else {
-                            this.mustUpdateRessources = true;
+                            this._mustUpdateRessources = true;
                             updateInDBCallback();
                         }
                     };
@@ -440,17 +447,17 @@ module BABYLON {
         }
 
         private _saveVersionIntoDBAsync(url: string, callback: (version: number) => void) {
-            if (this.isSupported && !this.hasReachedQuota && this.db) {
+            if (this._isSupported && !this._hasReachedQuota && this._db) {
                 try {
                     // Open a transaction to the database
-                    var transaction = this.db.transaction(["versions"], "readwrite");
+                    var transaction = this._db.transaction(["versions"], "readwrite");
 
                     // the transaction could abort because of a QuotaExceededError error
                     transaction.onabort = (event) => {
                         try {//backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                             var error = (<any>event.srcElement)['error'];
                             if (error && error.name === "QuotaExceededError") {
-                                this.hasReachedQuota = true;
+                                this._hasReachedQuota = true;
                             }
                         }
                         catch (ex) { }
@@ -458,10 +465,10 @@ module BABYLON {
                     };
 
                     transaction.oncomplete = (event) => {
-                        callback(this.manifestVersionFound);
+                        callback(this._manifestVersionFound);
                     };
 
-                    var newVersion = { sceneUrl: url, data: this.manifestVersionFound };
+                    var newVersion = { sceneUrl: url, data: this._manifestVersionFound };
 
                     // Put the scene into the database
                     var addRequest = transaction.objectStore("versions").put(newVersion);
@@ -489,21 +496,21 @@ module BABYLON {
          * @param errorCallback defines a callback to call on error
          * @param useArrayBuffer defines a boolean to use array buffer instead of text string
          */
-        public loadFileFromDB(url: string, sceneLoaded: (data: any) => void, progressCallBack?: (data: any) => void, errorCallback?: () => void, useArrayBuffer?: boolean) {
+        public loadFile(url: string, sceneLoaded: (data: any) => void, progressCallBack?: (data: any) => void, errorCallback?: () => void, useArrayBuffer?: boolean): void {
             var completeUrl = Database._ReturnFullUrlLocation(url);
 
             var saveAndLoadFile = () => {
                 // the scene is not yet in the DB, let's try to save it
-                this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
             };
 
             this._checkVersionFromDB(completeUrl, (version) => {
                 if (version !== -1) {
-                    if (!this.mustUpdateRessources) {
-                        this._loadFileFromDBAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
+                    if (!this._mustUpdateRessources) {
+                        this._loadFileAsync(completeUrl, sceneLoaded, saveAndLoadFile, useArrayBuffer);
                     }
                     else {
-                        this._saveFileIntoDBAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
+                        this._saveFileAsync(completeUrl, sceneLoaded, progressCallBack, useArrayBuffer, errorCallback);
                     }
                 }
                 else {
@@ -514,8 +521,8 @@ module BABYLON {
             });
         }
 
-        private _loadFileFromDBAsync(url: string, callback: (data?: any) => void, notInDBCallback: () => void, useArrayBuffer?: boolean) {
-            if (this.isSupported && this.db) {
+        private _loadFileAsync(url: string, callback: (data?: any) => void, notInDBCallback: () => void, useArrayBuffer?: boolean) {
+            if (this._isSupported && this._db) {
                 var targetStore: string;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -525,7 +532,7 @@ module BABYLON {
                 }
 
                 var file: any;
-                var transaction = this.db.transaction([targetStore]);
+                var transaction = this._db.transaction([targetStore]);
 
                 transaction.oncomplete = (event) => {
                     if (file) {
@@ -557,8 +564,8 @@ module BABYLON {
             }
         }
 
-        private _saveFileIntoDBAsync(url: string, callback: (data?: any) => void, progressCallback?: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any, useArrayBuffer?: boolean, errorCallback?: (data?: any) => void) {
-            if (this.isSupported) {
+        private _saveFileAsync(url: string, callback: (data?: any) => void, progressCallback?: (this: XMLHttpRequestEventTarget, ev: ProgressEvent) => any, useArrayBuffer?: boolean, errorCallback?: (data?: any) => void) {
+            if (this._isSupported) {
                 var targetStore: string;
                 if (url.indexOf(".babylon") !== -1) {
                     targetStore = "scenes";
@@ -583,12 +590,11 @@ module BABYLON {
                 xhr.addEventListener("load", () => {
                     if (xhr.status === 200 || (xhr.status < 400 && Tools.ValidateXHRData(xhr, !useArrayBuffer ? 1 : 6))) {
                         // Blob as response (XHR2)
-                        //fileData = xhr.responseText;
                         fileData = !useArrayBuffer ? xhr.responseText : xhr.response;
 
-                        if (!this.hasReachedQuota && this.db) {
+                        if (!this._hasReachedQuota && this._db) {
                             // Open a transaction to the database
-                            var transaction = this.db.transaction([targetStore], "readwrite");
+                            var transaction = this._db.transaction([targetStore], "readwrite");
 
                             // the transaction could abort because of a QuotaExceededError error
                             transaction.onabort = (event) => {
@@ -596,7 +602,7 @@ module BABYLON {
                                     //backwards compatibility with ts 1.0, srcElement doesn't have an "error" according to ts 1.3
                                     var error = (<any>event.srcElement)['error'];
                                     if (error && error.name === "QuotaExceededError") {
-                                        this.hasReachedQuota = true;
+                                        this._hasReachedQuota = true;
                                     }
                                 }
                                 catch (ex) { }
@@ -609,7 +615,7 @@ module BABYLON {
 
                             var newFile;
                             if (targetStore === "scenes") {
-                                newFile = { sceneUrl: url, data: fileData, version: this.manifestVersionFound };
+                                newFile = { sceneUrl: url, data: fileData, version: this._manifestVersionFound };
                             }
                             else {
                                 newFile = { textureUrl: url, data: fileData };
@@ -635,7 +641,7 @@ module BABYLON {
                     else {
                         if (xhr.status >= 400 && errorCallback) {
                             errorCallback(xhr);
-                        }else {
+                        } else {
                             callback();
                         }
                     }
@@ -649,7 +655,7 @@ module BABYLON {
                 xhr.send();
             }
             else {
-                Tools.Error("Error: IndexedDB not supported by your browser or BabylonJS Database is not open.");
+                Tools.Error("Error: IndexedDB not supported by your browser or Babylon.js Database is not open.");
                 callback();
             }
         }

+ 18 - 19
src/Tools/babylon.tools.ts

@@ -725,10 +725,10 @@ module BABYLON {
          * @param input url string, ArrayBuffer, or Blob to load
          * @param onLoad callback called when the image successfully loads
          * @param onError callback called when the image fails to load
-         * @param database database for caching
+         * @param offlineProvider offline provider for caching
          * @returns the HTMLImageElement of the loaded image
          */
-        public static LoadImage(input: string | ArrayBuffer | Blob, onLoad: (img: HTMLImageElement) => void, onError: (message?: string, exception?: any) => void, database: Nullable<Database>): HTMLImageElement {
+        public static LoadImage(input: string | ArrayBuffer | Blob, onLoad: (img: HTMLImageElement) => void, onError: (message?: string, exception?: any) => void, offlineProvider: Nullable<IOfflineProvider>): HTMLImageElement {
             let url: string;
             let usingObjectURL = false;
 
@@ -776,19 +776,18 @@ module BABYLON {
             img.addEventListener("load", loadHandler);
             img.addEventListener("error", errorHandler);
 
-            var noIndexedDB = () => {
+            var noOfflineSupport = () => {
                 img.src = url;
             };
 
-            var loadFromIndexedDB = () => {
-                if (database) {
-                    database.loadImageFromDB(url, img);
+            var loadFromOfflineSupport = () => {
+                if (offlineProvider) {
+                    offlineProvider.loadImage(url, img);
                 }
             };
 
-            //ANY database to do!
-            if (url.substr(0, 5) !== "data:" && database && database.enableTexturesOffline && Database.IsUASupportingBlobStorage) {
-                database.openAsync(loadFromIndexedDB, noIndexedDB);
+            if (url.substr(0, 5) !== "data:" && offlineProvider && offlineProvider.enableTexturesOffline) {
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport);
             }
             else {
                 if (url.indexOf("file:") !== -1) {
@@ -813,7 +812,7 @@ module BABYLON {
                     }
                 }
 
-                noIndexedDB();
+                noOfflineSupport();
             }
 
             return img;
@@ -824,12 +823,12 @@ module BABYLON {
          * @param url url string, ArrayBuffer, or Blob to load
          * @param onSuccess callback called when the file successfully loads
          * @param onProgress callback called while file is loading (if the server supports this mode)
-         * @param database  database for caching
+         * @param offlineProvider defines the offline provider for caching
          * @param useArrayBuffer defines a boolean indicating that date must be returned as ArrayBuffer
          * @param onError callback called when the file fails to load
          * @returns a file request object
          */
-        public static LoadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, database?: Database, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
+        public static LoadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, offlineProvider?: IOfflineProvider, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
             url = Tools.CleanUrl(url);
 
             url = Tools.PreprocessUrl(url);
@@ -931,8 +930,8 @@ module BABYLON {
             };
 
             // Caching all files
-            if (database && database.enableSceneOffline) {
-                const noIndexedDB = (request?: any) => {
+            if (offlineProvider && offlineProvider.enableSceneOffline) {
+                const noOfflineSupport = (request?: any) => {
                     if (request && request.status > 400) {
                         if (onError) {
                             onError(request);
@@ -944,14 +943,14 @@ module BABYLON {
                     }
                 };
 
-                const loadFromIndexedDB = () => {
+                const loadFromOfflineSupport = () => {
                     // TODO: database needs to support aborting and should return a IFileRequest
                     if (aborted) {
                         return;
                     }
 
-                    if (database) {
-                        database.loadFileFromDB(url, (data) => {
+                    if (offlineProvider) {
+                        offlineProvider.loadFile(url, (data) => {
                             if (!aborted) {
                                 onSuccess(data);
                             }
@@ -961,11 +960,11 @@ module BABYLON {
                             if (!aborted) {
                                 onProgress(event);
                             }
-                        } : undefined, noIndexedDB, useArrayBuffer);
+                        } : undefined, noOfflineSupport, useArrayBuffer);
                     }
                 };
 
-                database.openAsync(loadFromIndexedDB, noIndexedDB);
+                offlineProvider.open(loadFromOfflineSupport, noOfflineSupport);
             }
             else {
                 requestFile();

+ 8 - 7
src/babylon.scene.ts

@@ -890,11 +890,12 @@ module BABYLON {
         */
         public probesEnabled = true;
 
-        // Database
+        // Offline support
         /**
-         * @hidden
+         * Gets or sets the current offline provider to use to store scene data
+         * @see http://doc.babylonjs.com/how_to/caching_resources_in_indexeddb
          */
-        public database: Database;
+        public offlineProvider: IOfflineProvider;
 
         /**
          * Gets or sets the action manager associated with the scene
@@ -5388,8 +5389,8 @@ module BABYLON {
         }
 
         /** @hidden */
-        public _loadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, useDatabase?: boolean, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
-            let request = Tools.LoadFile(url, onSuccess, onProgress, useDatabase ? this.database : undefined, useArrayBuffer, onError);
+        public _loadFile(url: string, onSuccess: (data: string | ArrayBuffer, responseURL?: string) => void, onProgress?: (data: any) => void, useOfflineSupport?: boolean, useArrayBuffer?: boolean, onError?: (request?: XMLHttpRequest, exception?: any) => void): IFileRequest {
+            let request = Tools.LoadFile(url, onSuccess, onProgress, useOfflineSupport ? this.offlineProvider : undefined, useArrayBuffer, onError);
             this._activeRequests.push(request);
             request.onCompleteObservable.add((request) => {
                 this._activeRequests.splice(this._activeRequests.indexOf(request), 1);
@@ -5398,11 +5399,11 @@ module BABYLON {
         }
 
         /** @hidden */
-        public _loadFileAsync(url: string, useDatabase?: boolean, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
+        public _loadFileAsync(url: string, useOfflineSupport?: boolean, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
             return new Promise((resolve, reject) => {
                 this._loadFile(url, (data) => {
                     resolve(data);
-                }, undefined, useDatabase, useArrayBuffer, (request, exception) => {
+                }, undefined, useOfflineSupport, useArrayBuffer, (request, exception) => {
                     reject(exception);
                 });
             });

+ 15 - 12
tests/validation/validate.html

@@ -1,21 +1,23 @@
 <!DOCTYPE html>
 <html>
+
 <head>
 	<title>BabylonJS - Build validation page</title>
 	<link href="index.css" rel="stylesheet" />
-    <script src="https://preview.babylonjs.com/draco_decoder.js"></script>
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/gltf_validator.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.js"></script>
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-    <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
+	<script src="https://preview.babylonjs.com/draco_decoder_gltf.js"></script>
+	<script src="https://preview.babylonjs.com/cannon.js"></script>
+	<script src="https://preview.babylonjs.com/Oimo.js"></script>
+	<script src="https://preview.babylonjs.com/gltf_validator.js"></script>
+	<script src="https://preview.babylonjs.com/babylon.js"></script>
+	<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+
+	<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
 	<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
+	<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
 	<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
-    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>	
+	<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
 </head>
+
 <body>
 	<script src="validation.js"></script>
 	<script>
@@ -24,7 +26,7 @@
 
 		xhr.open("GET", "config.json", true);
 
-		xhr.addEventListener("load", function () {
+		xhr.addEventListener("load", function() {
 			if (xhr.status === 200) {
 
 				config = JSON.parse(xhr.responseText);
@@ -56,6 +58,7 @@
 		}, false);
 
 		xhr.send();
-    </script>	
+	</script>
 </body>
+
 </html>