فهرست منبع

Merge remote-tracking branch 'BabylonJS/master' into viewer-testing

Raanan Weber 7 سال پیش
والد
کامیت
b7dab434fe
71فایلهای تغییر یافته به همراه7829 افزوده شده و 7366 حذف شده
  1. 3319 3266
      Playground/babylon.d.txt
  2. BIN
      Playground/textures/BJS-logo_v3.png
  3. BIN
      Playground/textures/SpecularHDR.dds_thumb.jpg
  4. BIN
      Playground/textures/country.hdr_thumb.jpg
  5. BIN
      Playground/textures/cubemap_blank.jpg
  6. BIN
      Playground/textures/environment.dds_thumb.jpg
  7. BIN
      Playground/textures/environment.hdr_thumb.jpg
  8. BIN
      Playground/textures/forest.hdr_thumb.jpg
  9. BIN
      Playground/textures/grass.dds_thumb.jpg
  10. BIN
      Playground/textures/impact.png
  11. BIN
      Playground/textures/leopard_fur.JPG
  12. BIN
      Playground/textures/night.hdr_thumb.jpg
  13. BIN
      Playground/textures/parking.hdr_thumb.jpg
  14. BIN
      Playground/textures/particle.png
  15. BIN
      Playground/textures/room.hdr_thumb.jpg
  16. BIN
      Playground/textures/sparkle.png
  17. BIN
      Playground/textures/speckles.jpg
  18. 3318 3277
      dist/preview release/babylon.d.ts
  19. 44 44
      dist/preview release/babylon.js
  20. 94 19
      dist/preview release/babylon.max.js
  21. 94 19
      dist/preview release/babylon.no-module.max.js
  22. 44 44
      dist/preview release/babylon.worker.js
  23. 94 19
      dist/preview release/es6.js
  24. 1 1
      dist/preview release/gltf2Interface/package.json
  25. 1 1
      dist/preview release/gui/package.json
  26. 1 1
      dist/preview release/inspector/package.json
  27. 16 10
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  28. 8 4
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  29. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  30. 14 2
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  31. 51 33
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  32. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  33. 22 12
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  34. 53 37
      dist/preview release/loaders/babylon.glTFFileLoader.js
  35. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  36. 22 12
      dist/preview release/loaders/babylonjs.loaders.d.ts
  37. 53 37
      dist/preview release/loaders/babylonjs.loaders.js
  38. 4 4
      dist/preview release/loaders/babylonjs.loaders.min.js
  39. 22 12
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  40. 2 2
      dist/preview release/loaders/package.json
  41. 1 1
      dist/preview release/materialsLibrary/package.json
  42. 1 1
      dist/preview release/postProcessesLibrary/package.json
  43. 1 1
      dist/preview release/proceduralTexturesLibrary/package.json
  44. 2 2
      dist/preview release/serializers/package.json
  45. 2 136
      dist/preview release/typedocValidationBaseline.json
  46. 52 52
      dist/preview release/viewer/babylon.viewer.js
  47. 219 59
      dist/preview release/viewer/babylon.viewer.max.js
  48. 1 1
      dist/preview release/viewer/package.json
  49. 2 1
      dist/preview release/what's new.md
  50. 8 10
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  51. 46 36
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  52. 13 0
      loaders/src/glTF/babylon.glTFFileLoader.ts
  53. 1 1
      package.json
  54. 1 0
      sandbox/Assets/Icon_Dashboard.svg
  55. 1 0
      sandbox/Assets/Icon_EditModel.svg
  56. 1 0
      sandbox/Assets/Icon_Fullscreen.svg
  57. 1 0
      sandbox/Assets/Icon_OpenFile.svg
  58. 7 21
      sandbox/index-local.html
  59. 38 106
      sandbox/index.css
  60. 7 21
      sandbox/index.html
  61. 8 24
      sandbox/index.js
  62. 1 1
      src/Animations/babylon.runtimeAnimation.ts
  63. 6 1
      src/Engine/babylon.engine.ts
  64. 3 2
      src/Loading/babylon.sceneLoader.ts
  65. 2 2
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  66. 4 2
      src/Materials/Textures/babylon.videoTexture.ts
  67. 3 5
      src/Shaders/ShadersInclude/pbrFunctions.fx
  68. 6 6
      src/Shaders/pbr.fragment.fx
  69. 56 9
      src/Tools/babylon.database.ts
  70. 22 2
      src/Tools/babylon.promise.ts
  71. 29 0
      tests/unit/babylon/src/Tools/babylon.promise.tests.ts

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3319 - 3266
Playground/babylon.d.txt


BIN
Playground/textures/BJS-logo_v3.png


BIN
Playground/textures/SpecularHDR.dds_thumb.jpg


BIN
Playground/textures/country.hdr_thumb.jpg


BIN
Playground/textures/cubemap_blank.jpg


BIN
Playground/textures/environment.dds_thumb.jpg


BIN
Playground/textures/environment.hdr_thumb.jpg


BIN
Playground/textures/forest.hdr_thumb.jpg


BIN
Playground/textures/grass.dds_thumb.jpg


BIN
Playground/textures/impact.png


BIN
Playground/textures/leopard_fur.JPG


BIN
Playground/textures/night.hdr_thumb.jpg


BIN
Playground/textures/parking.hdr_thumb.jpg


BIN
Playground/textures/particle.png


BIN
Playground/textures/room.hdr_thumb.jpg


BIN
Playground/textures/sparkle.png


BIN
Playground/textures/speckles.jpg


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3318 - 3277
dist/preview release/babylon.d.ts


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 44 - 44
dist/preview release/babylon.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 94 - 19
dist/preview release/babylon.max.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 94 - 19
dist/preview release/babylon.no-module.max.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 44 - 44
dist/preview release/babylon.worker.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 94 - 19
dist/preview release/es6.js


+ 1 - 1
dist/preview release/gltf2Interface/package.json

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/gui/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/inspector/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 16 - 10
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -98,6 +98,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -199,6 +203,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -743,16 +751,14 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);

+ 8 - 4
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -84,6 +84,10 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -262,6 +266,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -389,6 +394,7 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -1968,16 +1974,14 @@ var BABYLON;
                 this.compileMaterials = false;
                 this.useClipPlane = false;
                 this.compileShadowGenerators = false;
-                this.onDisposeObservable = new BABYLON.Observable();
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
                 this.onCameraLoadedObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
+                this.onDisposeObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
-                /**
-                * State of the loader
-                */
                 this.state = null;
             }
             GLTFLoader.RegisterExtension = function (extension) {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 14 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -98,6 +98,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -199,6 +203,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -495,8 +503,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -520,6 +528,10 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;

+ 51 - 33
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -84,6 +84,10 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -262,6 +266,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -389,6 +394,7 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -648,6 +654,10 @@ var BABYLON;
                  */
                 this.compileShadowGenerators = false;
                 /**
+                 * Function called before loading a url referenced by the asset.
+                 */
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+                /**
                  * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
                  */
                 this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -681,13 +691,13 @@ var BABYLON;
             }
             /** @hidden */
             GLTFLoader._Register = function (name, factory) {
-                if (GLTFLoader._Factories[name]) {
+                if (GLTFLoader._ExtensionFactories[name]) {
                     BABYLON.Tools.Error("Extension with the name '" + name + "' already exists");
                     return;
                 }
-                GLTFLoader._Factories[name] = factory;
+                GLTFLoader._ExtensionFactories[name] = factory;
                 // Keep the order of registration so that extensions registered first are called first.
-                GLTFLoader._Names.push(name);
+                GLTFLoader._ExtensionNames.push(name);
             };
             Object.defineProperty(GLTFLoader.prototype, "state", {
                 /**
@@ -810,15 +820,17 @@ var BABYLON;
                     });
                     return resultPromise;
                 }).catch(function (error) {
-                    BABYLON.Tools.Error("glTF Loader: " + error.message);
-                    _this._clear();
-                    throw error;
+                    if (!_this._disposed) {
+                        BABYLON.Tools.Error("glTF Loader: " + error.message);
+                        _this._clear();
+                        throw error;
+                    }
                 });
             };
             GLTFLoader.prototype._loadExtensions = function () {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_1 = _a[_i];
-                    var extension = GLTFLoader._Factories[name_1](this);
+                    var extension = GLTFLoader._ExtensionFactories[name_1](this);
                     this._extensions[name_1] = extension;
                     this.onExtensionLoadedObservable.notifyObservers(extension);
                 }
@@ -1391,7 +1403,9 @@ var BABYLON;
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
                 var _this = this;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
-                if (!targetNode._babylonMesh) {
+                // Ignore animations that have no animation targets.
+                if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||
+                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonAnimationTargets)) {
                     return Promise.resolve();
                 }
                 // Ignore animations targeting TRS of skinned nodes.
@@ -1895,31 +1909,35 @@ var BABYLON;
                 if (BABYLON.Tools.IsBase64(uri)) {
                     return Promise.resolve(new Uint8Array(BABYLON.Tools.DecodeBase64(uri)));
                 }
-                return new Promise(function (resolve, reject) {
-                    var request = BABYLON.Tools.LoadFile(_this._rootUrl + uri, function (data) {
-                        if (!_this._disposed) {
-                            resolve(new Uint8Array(data));
-                        }
-                    }, function (event) {
+                return this.preprocessUrlAsync(this._rootUrl + uri).then(function (url) {
+                    return new Promise(function (resolve, reject) {
                         if (!_this._disposed) {
-                            try {
-                                if (request && _this._state === BABYLON.GLTFLoaderState.LOADING) {
-                                    request._lengthComputable = event.lengthComputable;
-                                    request._loaded = event.loaded;
-                                    request._total = event.total;
-                                    _this._onProgress();
+                            var request_1 = BABYLON.Tools.LoadFile(url, function (data) {
+                                if (!_this._disposed) {
+                                    resolve(new Uint8Array(data));
                                 }
-                            }
-                            catch (e) {
-                                reject(e);
-                            }
-                        }
-                    }, _this._babylonScene.database, true, function (request, exception) {
-                        if (!_this._disposed) {
-                            reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                            }, function (event) {
+                                if (!_this._disposed) {
+                                    try {
+                                        if (request_1 && _this._state === BABYLON.GLTFLoaderState.LOADING) {
+                                            request_1._lengthComputable = event.lengthComputable;
+                                            request_1._loaded = event.loaded;
+                                            request_1._total = event.total;
+                                            _this._onProgress();
+                                        }
+                                    }
+                                    catch (e) {
+                                        reject(e);
+                                    }
+                                }
+                            }, _this._babylonScene.database, true, function (request, exception) {
+                                if (!_this._disposed) {
+                                    reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                                }
+                            });
+                            _this._requests.push(request_1);
                         }
                     });
-                    _this._requests.push(request);
                 });
             };
             GLTFLoader.prototype._onProgress = function () {
@@ -2110,7 +2128,7 @@ var BABYLON;
             };
             /** @hidden */
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_5 = _a[_i];
                     var extension = this._extensions[name_5];
                     if (extension.enabled) {
@@ -2122,8 +2140,8 @@ var BABYLON;
                 }
                 return null;
             };
-            GLTFLoader._Names = new Array();
-            GLTFLoader._Factories = {};
+            GLTFLoader._ExtensionNames = new Array();
+            GLTFLoader._ExtensionFactories = {};
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 22 - 12
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -98,6 +98,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -199,6 +203,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -743,16 +751,14 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1072,8 +1078,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -1097,6 +1103,10 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;

+ 53 - 37
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -84,6 +84,10 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -262,6 +266,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -389,6 +394,7 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -1968,16 +1974,14 @@ var BABYLON;
                 this.compileMaterials = false;
                 this.useClipPlane = false;
                 this.compileShadowGenerators = false;
-                this.onDisposeObservable = new BABYLON.Observable();
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
                 this.onCameraLoadedObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
+                this.onDisposeObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
-                /**
-                * State of the loader
-                */
                 this.state = null;
             }
             GLTFLoader.RegisterExtension = function (extension) {
@@ -2864,6 +2868,10 @@ var BABYLON;
                  */
                 this.compileShadowGenerators = false;
                 /**
+                 * Function called before loading a url referenced by the asset.
+                 */
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+                /**
                  * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
                  */
                 this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -2897,13 +2905,13 @@ var BABYLON;
             }
             /** @hidden */
             GLTFLoader._Register = function (name, factory) {
-                if (GLTFLoader._Factories[name]) {
+                if (GLTFLoader._ExtensionFactories[name]) {
                     BABYLON.Tools.Error("Extension with the name '" + name + "' already exists");
                     return;
                 }
-                GLTFLoader._Factories[name] = factory;
+                GLTFLoader._ExtensionFactories[name] = factory;
                 // Keep the order of registration so that extensions registered first are called first.
-                GLTFLoader._Names.push(name);
+                GLTFLoader._ExtensionNames.push(name);
             };
             Object.defineProperty(GLTFLoader.prototype, "state", {
                 /**
@@ -3026,15 +3034,17 @@ var BABYLON;
                     });
                     return resultPromise;
                 }).catch(function (error) {
-                    BABYLON.Tools.Error("glTF Loader: " + error.message);
-                    _this._clear();
-                    throw error;
+                    if (!_this._disposed) {
+                        BABYLON.Tools.Error("glTF Loader: " + error.message);
+                        _this._clear();
+                        throw error;
+                    }
                 });
             };
             GLTFLoader.prototype._loadExtensions = function () {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_1 = _a[_i];
-                    var extension = GLTFLoader._Factories[name_1](this);
+                    var extension = GLTFLoader._ExtensionFactories[name_1](this);
                     this._extensions[name_1] = extension;
                     this.onExtensionLoadedObservable.notifyObservers(extension);
                 }
@@ -3607,7 +3617,9 @@ var BABYLON;
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
                 var _this = this;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
-                if (!targetNode._babylonMesh) {
+                // Ignore animations that have no animation targets.
+                if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||
+                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonAnimationTargets)) {
                     return Promise.resolve();
                 }
                 // Ignore animations targeting TRS of skinned nodes.
@@ -4111,31 +4123,35 @@ var BABYLON;
                 if (BABYLON.Tools.IsBase64(uri)) {
                     return Promise.resolve(new Uint8Array(BABYLON.Tools.DecodeBase64(uri)));
                 }
-                return new Promise(function (resolve, reject) {
-                    var request = BABYLON.Tools.LoadFile(_this._rootUrl + uri, function (data) {
+                return this.preprocessUrlAsync(this._rootUrl + uri).then(function (url) {
+                    return new Promise(function (resolve, reject) {
                         if (!_this._disposed) {
-                            resolve(new Uint8Array(data));
-                        }
-                    }, function (event) {
-                        if (!_this._disposed) {
-                            try {
-                                if (request && _this._state === BABYLON.GLTFLoaderState.LOADING) {
-                                    request._lengthComputable = event.lengthComputable;
-                                    request._loaded = event.loaded;
-                                    request._total = event.total;
-                                    _this._onProgress();
+                            var request_1 = BABYLON.Tools.LoadFile(url, function (data) {
+                                if (!_this._disposed) {
+                                    resolve(new Uint8Array(data));
                                 }
-                            }
-                            catch (e) {
-                                reject(e);
-                            }
-                        }
-                    }, _this._babylonScene.database, true, function (request, exception) {
-                        if (!_this._disposed) {
-                            reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                            }, function (event) {
+                                if (!_this._disposed) {
+                                    try {
+                                        if (request_1 && _this._state === BABYLON.GLTFLoaderState.LOADING) {
+                                            request_1._lengthComputable = event.lengthComputable;
+                                            request_1._loaded = event.loaded;
+                                            request_1._total = event.total;
+                                            _this._onProgress();
+                                        }
+                                    }
+                                    catch (e) {
+                                        reject(e);
+                                    }
+                                }
+                            }, _this._babylonScene.database, true, function (request, exception) {
+                                if (!_this._disposed) {
+                                    reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                                }
+                            });
+                            _this._requests.push(request_1);
                         }
                     });
-                    _this._requests.push(request);
                 });
             };
             GLTFLoader.prototype._onProgress = function () {
@@ -4326,7 +4342,7 @@ var BABYLON;
             };
             /** @hidden */
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_5 = _a[_i];
                     var extension = this._extensions[name_5];
                     if (extension.enabled) {
@@ -4338,8 +4354,8 @@ var BABYLON;
                 }
                 return null;
             };
-            GLTFLoader._Names = new Array();
-            GLTFLoader._Factories = {};
+            GLTFLoader._ExtensionNames = new Array();
+            GLTFLoader._ExtensionFactories = {};
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 22 - 12
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -194,6 +194,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -295,6 +299,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -839,16 +847,14 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1168,8 +1174,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -1193,6 +1199,10 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;

+ 53 - 37
dist/preview release/loaders/babylonjs.loaders.js

@@ -1084,6 +1084,10 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -1262,6 +1266,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -1389,6 +1394,7 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -2968,16 +2974,14 @@ var BABYLON;
                 this.compileMaterials = false;
                 this.useClipPlane = false;
                 this.compileShadowGenerators = false;
-                this.onDisposeObservable = new BABYLON.Observable();
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
                 this.onCameraLoadedObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
+                this.onDisposeObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
-                /**
-                * State of the loader
-                */
                 this.state = null;
             }
             GLTFLoader.RegisterExtension = function (extension) {
@@ -3846,6 +3850,10 @@ var BABYLON;
                  */
                 this.compileShadowGenerators = false;
                 /**
+                 * Function called before loading a url referenced by the asset.
+                 */
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+                /**
                  * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
                  */
                 this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -3879,13 +3887,13 @@ var BABYLON;
             }
             /** @hidden */
             GLTFLoader._Register = function (name, factory) {
-                if (GLTFLoader._Factories[name]) {
+                if (GLTFLoader._ExtensionFactories[name]) {
                     BABYLON.Tools.Error("Extension with the name '" + name + "' already exists");
                     return;
                 }
-                GLTFLoader._Factories[name] = factory;
+                GLTFLoader._ExtensionFactories[name] = factory;
                 // Keep the order of registration so that extensions registered first are called first.
-                GLTFLoader._Names.push(name);
+                GLTFLoader._ExtensionNames.push(name);
             };
             Object.defineProperty(GLTFLoader.prototype, "state", {
                 /**
@@ -4008,15 +4016,17 @@ var BABYLON;
                     });
                     return resultPromise;
                 }).catch(function (error) {
-                    BABYLON.Tools.Error("glTF Loader: " + error.message);
-                    _this._clear();
-                    throw error;
+                    if (!_this._disposed) {
+                        BABYLON.Tools.Error("glTF Loader: " + error.message);
+                        _this._clear();
+                        throw error;
+                    }
                 });
             };
             GLTFLoader.prototype._loadExtensions = function () {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_1 = _a[_i];
-                    var extension = GLTFLoader._Factories[name_1](this);
+                    var extension = GLTFLoader._ExtensionFactories[name_1](this);
                     this._extensions[name_1] = extension;
                     this.onExtensionLoadedObservable.notifyObservers(extension);
                 }
@@ -4589,7 +4599,9 @@ var BABYLON;
             GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
                 var _this = this;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
-                if (!targetNode._babylonMesh) {
+                // Ignore animations that have no animation targets.
+                if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||
+                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonAnimationTargets)) {
                     return Promise.resolve();
                 }
                 // Ignore animations targeting TRS of skinned nodes.
@@ -5093,31 +5105,35 @@ var BABYLON;
                 if (BABYLON.Tools.IsBase64(uri)) {
                     return Promise.resolve(new Uint8Array(BABYLON.Tools.DecodeBase64(uri)));
                 }
-                return new Promise(function (resolve, reject) {
-                    var request = BABYLON.Tools.LoadFile(_this._rootUrl + uri, function (data) {
+                return this.preprocessUrlAsync(this._rootUrl + uri).then(function (url) {
+                    return new Promise(function (resolve, reject) {
                         if (!_this._disposed) {
-                            resolve(new Uint8Array(data));
-                        }
-                    }, function (event) {
-                        if (!_this._disposed) {
-                            try {
-                                if (request && _this._state === BABYLON.GLTFLoaderState.LOADING) {
-                                    request._lengthComputable = event.lengthComputable;
-                                    request._loaded = event.loaded;
-                                    request._total = event.total;
-                                    _this._onProgress();
+                            var request_1 = BABYLON.Tools.LoadFile(url, function (data) {
+                                if (!_this._disposed) {
+                                    resolve(new Uint8Array(data));
                                 }
-                            }
-                            catch (e) {
-                                reject(e);
-                            }
-                        }
-                    }, _this._babylonScene.database, true, function (request, exception) {
-                        if (!_this._disposed) {
-                            reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                            }, function (event) {
+                                if (!_this._disposed) {
+                                    try {
+                                        if (request_1 && _this._state === BABYLON.GLTFLoaderState.LOADING) {
+                                            request_1._lengthComputable = event.lengthComputable;
+                                            request_1._loaded = event.loaded;
+                                            request_1._total = event.total;
+                                            _this._onProgress();
+                                        }
+                                    }
+                                    catch (e) {
+                                        reject(e);
+                                    }
+                                }
+                            }, _this._babylonScene.database, true, function (request, exception) {
+                                if (!_this._disposed) {
+                                    reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                                }
+                            });
+                            _this._requests.push(request_1);
                         }
                     });
-                    _this._requests.push(request);
                 });
             };
             GLTFLoader.prototype._onProgress = function () {
@@ -5308,7 +5324,7 @@ var BABYLON;
             };
             /** @hidden */
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_5 = _a[_i];
                     var extension = this._extensions[name_5];
                     if (extension.enabled) {
@@ -5320,8 +5336,8 @@ var BABYLON;
                 }
                 return null;
             };
-            GLTFLoader._Names = new Array();
-            GLTFLoader._Factories = {};
+            GLTFLoader._ExtensionNames = new Array();
+            GLTFLoader._ExtensionFactories = {};
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4 - 4
dist/preview release/loaders/babylonjs.loaders.min.js


+ 22 - 12
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -201,6 +201,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -302,6 +306,10 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -846,16 +854,14 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1175,8 +1181,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -1200,6 +1206,10 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;

+ 2 - 2
dist/preview release/loaders/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "3.2.0-beta.5"
+        "babylonjs-gltf2interface": "3.2.0-rc.1"
     },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"

+ 1 - 1
dist/preview release/materialsLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/postProcessesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/proceduralTexturesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 2 - 2
dist/preview release/serializers/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "3.2.0-beta.5"
+        "babylonjs-gltf2interface": "3.2.0-rc.1"
     },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"

+ 2 - 136
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 4354,
+  "errors": 4330,
   "babylon.typedoc.json": {
-    "errors": 4354,
+    "errors": 4330,
     "Animatable": {
       "Class": {
         "Comments": {
@@ -4926,140 +4926,6 @@
         }
       }
     },
-    "Database": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Constructor": {
-        "new Database": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "urlToScene": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "callbackManifestChecked": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      },
-      "Property": {
-        "enableSceneOffline": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "enableTexturesOffline": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "IDBStorageEnabled": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "IsUASupportingBlobStorage": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "ReturnFullUrlLocation": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "parseURL": {
-          "Naming": {
-            "NotPascalCase": true
-          },
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      },
-      "Method": {
-        "checkManifestFile": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "loadFileFromDB": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "url": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "sceneLoaded": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "progressCallBack": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "errorCallback": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "useArrayBuffer": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "loadImageFromDB": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "url": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "image": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "openAsync": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "successCallback": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "errorCallback": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      }
-    },
     "DebugLayer": {
       "Class": {
         "Comments": {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 52 - 52
dist/preview release/viewer/babylon.viewer.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 219 - 59
dist/preview release/viewer/babylon.viewer.max.js


+ 1 - 1
dist/preview release/viewer/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-viewer",
     "description": "A simple-to-use viewer based on BabylonJS to display 3D elements natively",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 2 - 1
dist/preview release/what's new.md

@@ -21,7 +21,7 @@
 - New [glTF exporter](http://doc.babylonjs.com/resources/3dsmax_to_gltf) for Autodesk 3dsmax ([Noalak](https://github.com/Noalak))
 - Physics - Latest production version of Oimo.js is being used - 1.0.9 ([RaananW](https://github.com/RaananW))
 - Introduces [PCF](https://doc.babylonjs.com/babylon101/shadows#percentage-closer-filtering-webgl2-only) and [PCSS](https://doc.babylonjs.com/babylon101/shadows#contact-hardening-shadow-webgl2-only) shadow support in Webgl 2 ([sebavan](https://github.com/sebavan)))
-- Introduces PBR Specular Anti Aliasing support ([sebavan](https://github.com/sebavan)))
+- Introduces [PBR Specular Anti Aliasing support](https://doc.babylonjs.com/how_to/physically_based_rendering_master#specular-aliasing) ([sebavan](https://github.com/sebavan)))
 
 ## Documentation
 
@@ -118,6 +118,7 @@
 - Added alphaCutOff support for StandardMaterial ([deltakosh](https://github.com/deltakosh))
 - Add support for sparse accessors to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 - Add support for cameras to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
+- Add support for preprocessing urls to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
 
 ## Bug fixes
 

+ 8 - 10
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1568,18 +1568,16 @@ module BABYLON.GLTF1 {
         public compileMaterials = false;
         public useClipPlane = false;
         public compileShadowGenerators = false;
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
 
-        public onDisposeObservable = new Observable<IGLTFLoader>();
-        public onMeshLoadedObservable = new Observable<AbstractMesh>();
-        public onTextureLoadedObservable = new Observable<BaseTexture>();
-        public onMaterialLoadedObservable = new Observable<Material>();
-        public onCameraLoadedObservable = new Observable<Camera>();
-        public onCompleteObservable = new Observable<IGLTFLoader>();
-        public onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
+        public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
+        public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
+        public readonly onMaterialLoadedObservable = new Observable<Material>();
+        public readonly onCameraLoadedObservable = new Observable<Camera>();
+        public readonly onCompleteObservable = new Observable<IGLTFLoader>();
+        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
+        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
-        /**
-        * State of the loader
-        */
         public state: Nullable<GLTFLoaderState> = null;
 
         public dispose(): void {}

+ 46 - 36
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -39,20 +39,20 @@ module BABYLON.GLTF2 {
         private _progressCallback?: (event: SceneLoaderProgressEvent) => void;
         private _requests = new Array<IFileRequestInfo>();
 
-        private static _Names = new Array<string>();
-        private static _Factories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
+        private static _ExtensionNames = new Array<string>();
+        private static _ExtensionFactories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
 
         /** @hidden */
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
-            if (GLTFLoader._Factories[name]) {
+            if (GLTFLoader._ExtensionFactories[name]) {
                 Tools.Error(`Extension with the name '${name}' already exists`);
                 return;
             }
 
-            GLTFLoader._Factories[name] = factory;
+            GLTFLoader._ExtensionFactories[name] = factory;
 
             // Keep the order of registration so that extensions registered first are called first.
-            GLTFLoader._Names.push(name);
+            GLTFLoader._ExtensionNames.push(name);
         }
 
         /**
@@ -81,6 +81,11 @@ module BABYLON.GLTF2 {
         public compileShadowGenerators = false;
 
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
@@ -118,7 +123,6 @@ module BABYLON.GLTF2 {
          */
         public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
-
         /**
          * Loader state or null if the loader is not active.
          */
@@ -254,15 +258,17 @@ module BABYLON.GLTF2 {
 
                 return resultPromise;
             }).catch(error => {
-                Tools.Error(`glTF Loader: ${error.message}`);
-                this._clear();
-                throw error;
+                if (!this._disposed) {
+                    Tools.Error(`glTF Loader: ${error.message}`);
+                    this._clear();
+                    throw error;
+                }
             });
         }
 
         private _loadExtensions(): void {
-            for (const name of GLTFLoader._Names) {
-                const extension = GLTFLoader._Factories[name](this);
+            for (const name of GLTFLoader._ExtensionNames) {
+                const extension = GLTFLoader._ExtensionFactories[name](this);
                 this._extensions[name] = extension;
 
                 this.onExtensionLoadedObservable.notifyObservers(extension);
@@ -1516,33 +1522,37 @@ module BABYLON.GLTF2 {
                 return Promise.resolve(new Uint8Array(Tools.DecodeBase64(uri)));
             }
 
-            return new Promise((resolve, reject) => {
-                const request = Tools.LoadFile(this._rootUrl + uri, data => {
-                    if (!this._disposed) {
-                        resolve(new Uint8Array(data as ArrayBuffer));
-                    }
-                }, event => {
+            return this.preprocessUrlAsync(this._rootUrl + uri).then(url => {
+                return new Promise<ArrayBufferView>((resolve, reject) => {
                     if (!this._disposed) {
-                        try {
-                            if (request && this._state === GLTFLoaderState.LOADING) {
-                                request._lengthComputable = event.lengthComputable;
-                                request._loaded = event.loaded;
-                                request._total = event.total;
-                                this._onProgress();
+                        const request = Tools.LoadFile(url, data => {
+                            if (!this._disposed) {
+                                resolve(new Uint8Array(data as ArrayBuffer));
                             }
-                        }
-                        catch (e) {
-                            reject(e);
-                        }
-                    }
-                }, this._babylonScene.database, true, (request, exception) => {
-                    if (!this._disposed) {
-                        reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
-                    }
-                }) as IFileRequestInfo;
+                        }, event => {
+                            if (!this._disposed) {
+                                try {
+                                    if (request && this._state === GLTFLoaderState.LOADING) {
+                                        request._lengthComputable = event.lengthComputable;
+                                        request._loaded = event.loaded;
+                                        request._total = event.total;
+                                        this._onProgress();
+                                    }
+                                }
+                                catch (e) {
+                                    reject(e);
+                                }
+                            }
+                        }, this._babylonScene.database, true, (request, exception) => {
+                            if (!this._disposed) {
+                                reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
+                            }
+                        }) as IFileRequestInfo;
 
-                this._requests.push(request);
-            })
+                        this._requests.push(request);
+                    }
+                });
+            });
         }
 
         private _onProgress(): void {
@@ -1762,7 +1772,7 @@ module BABYLON.GLTF2 {
 
         /** @hidden */
         public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {
-            for (const name of GLTFLoader._Names) {
+            for (const name of GLTFLoader._ExtensionNames) {
                 const extension = this._extensions[name];
                 if (extension.enabled) {
                     const promise = actionAsync(extension);

+ 13 - 0
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -116,6 +116,11 @@ module BABYLON {
         compileShadowGenerators: boolean;
 
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -249,6 +254,11 @@ module BABYLON {
         public compileShadowGenerators = false;
 
         /**
+         * Function called before loading a url referenced by the asset.
+         */
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
@@ -415,6 +425,8 @@ module BABYLON {
                 this._loader = null;
             }
 
+            this.preprocessUrlAsync = url => Promise.resolve(url);
+
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -560,6 +572,7 @@ module BABYLON {
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
             loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
             loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));

+ 1 - 1
package.json

@@ -9,7 +9,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
sandbox/Assets/Icon_Dashboard.svg


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
sandbox/Assets/Icon_EditModel.svg


+ 1 - 0
sandbox/Assets/Icon_Fullscreen.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160"><defs><style>.cls-1{fill:#fff;}</style></defs><title>Icon_Fullscreen</title><path class="cls-1" d="M117.66,42.34v26.9h-5.38V51.54L51.54,112.28h17.7v5.38H42.34V90.76h5.38v17.7l60.74-60.74H90.76V42.34Z"/></svg>

+ 1 - 0
sandbox/Assets/Icon_OpenFile.svg

@@ -0,0 +1 @@
+<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160"><defs><style>.cls-1{fill:#fff;}</style></defs><title>Icon_OpenFile</title><path class="cls-1" d="M49.45,113H96.53v4.7H44.74V42.34h41L106,62.53V80h-4.71V65.88H82.41V47h-33ZM87.12,61.17H97.89L87.12,50.39Zm24.82,37.55-6-6v24.9h-4.71V92.76l-6,6-3.31-3.31L103.6,83.75l11.66,11.66Z"/></svg>

+ 7 - 21
sandbox/index-local.html

@@ -11,31 +11,17 @@
     <canvas id="renderCanvas"></canvas>
     <div id="logo">
     </div>
-    <div id="help01" class="help">
-        <span class="helpText">Press this button to open your assets' files</span>
-        <img id="helpArrow" src="./Assets/FlecheTuto.png" />
-    </div>
-    <div id="help02" class="help2">
-        <span class="helpText">Or directly drag'n'drop your files in the browser</span>
-    </div>
     <div id="footer" class="footer">
         <div class="footerLeft">
-            Powered by <a href="http://www.babylonjs.com/" target="_blank">Babylon.js</a><br />
         </div>
         <div class="footerRight">
-            <ul>
-                <li id="btnFullscreen">
-                    <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
-                </li>
-                <li id="btnPerf">
-                    <img src="./Assets/BtnPerf.png" alt="Display inspector" title="Display inspector" />
-                </li>
-                <li id="btnFiles">
-                    <div class="custom-upload" title="Open your .babylon scene from your hard drive">
-                        <input type="file" id="files" multiple />
-                    </div>
-                </li>
-            </ul>
+            <a href="#" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
+            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></i></a> 
+            <a href="#">
+                <div class="custom-upload" title="Open your scene from your hard drive (.babylon, .gltf, .glb, .obj)">
+                    <input type="file" id="files" multiple />
+                </div>
+            </a>
         </div>
     </div>
     <div id="errorZone"></div>

+ 38 - 106
sandbox/index.css

@@ -7,46 +7,6 @@
     font-family: "Segoe WP", "Segoe UI", "Verdana", "Arial";
 }
 
-#DebugLayerLogs {
-    height: 100px !important;   
-}
-
-    #DebugLayerLogs > div:first-child {
-        background-color: #3B789A !important;
-    }
-
-#DebugLayerStats {
-    margin-top: 2px !important;
-}
-
-#DebugLayerStats div:nth-child(2) {
-    max-height: 180px !important;
-}
-
-    #DebugLayerStats > div:first-child {
-        background-color: #3B789A !important;
-    }
-
-#DebugLayerOptions {
-    overflow-y: hidden !important;
-}
-
-#DebugLayerOptions > div:first-child {
-    background-color: #3B789A !important;
-}
-
-#DebugLayerTree > div:first-child {
-    background-color: #3B789A !important;
-}
-
-a {
-    color: white;
-}
-
-    a:visited {
-        color: white;
-    }
-
 .hidden {
     display: none;
 }
@@ -122,38 +82,30 @@ a {
     width: 85px;
 }
 
-.footer {
-    position: absolute;
-    width: 100%;
-    height: 60px;
-    bottom: 0;
-    background-color: #3B789A;
-    padding-top: 5px;
-    padding-left: 15px;
+a {
+    color: white;
 }
 
-.perffooter {
+    a:visited {
+        color: white;
+    }
+
+
+.footer {
     position: absolute;
     width: 100%;
-    height: 60px;
-    bottom: 0px;
+    height: 56px;
+    bottom: 0;
     background-color: #3B789A;
-    padding-top: 5px;
     padding-left: 15px;
-        transition: all 0.5s ease;
-    -webkit-transition: all 0.5s ease;
 }
 
-    .perffooter.shown {
-        transform: translateY(-65px);
-        -webkit-transform: translateY(-65px);
-    }
-
 .footerRight {
     display: inline;
     position: absolute;
     bottom: 0;
     right: 10px;
+    top: 0px;
 }
 
 .footerLeft {
@@ -163,12 +115,35 @@ a {
     color: white;
 }
 
+.footerRight a {
+    float: left; /* Float links side by side */
+    width: 56px; 
+    height: 56px;
+    margin: 0px;
+    padding: 0;
+    transition: all 0.3s ease; /* Add transition for hover effects */
+}
+
+.footerRight a img {
+    width: 48px; 
+    height: 48px;
+    margin: 4px;
+}
+
+.footerRight a:hover {
+    background-color: #162D3A; /* Add a hover color */
+}
+
+.footerRight a:active {
+    background-color: #2c5a74; /* Add a hover color */
+}
+
 .custom-upload {
     position: relative;
-    background:url(./Assets/BtnDragdrop.png) center right no-repeat;
-    height: 56px;
-    width: 56px;
-    margin: 10px 20px 5px 5px;
+    background:url(./Assets/Icon_OpenFile.svg) center right no-repeat;
+    width: 48px; 
+    height: 48px;
+    margin: 4px;
 }
 
 .custom-upload input[type=file]
@@ -191,45 +166,12 @@ a {
     background-position: center;
 }
 
-#btnFullscreen {
-    margin-top: 10px;
-    margin-right: 25px;
-}
-
-#btnPerf {
-    margin-top: 10px;
-    margin-right: 15px;
-}
-
-ul {
- padding:0;
- margin:0;
- list-style-type:none;
- }
-
-li {
- float:left;
- }
-
 #btnDownArrow {
     position: absolute;
     bottom: 35px;
     right: 30px;
 }
 
-#miscCounters {
-    position: relative;
-    top: 18px;
-    height: 60px;
-    -webkit-column-width: 150px;
-    -moz-column-width: 150px;
-    -ms-column-width: 150px;
-    -o-column-width: 150px;
-    column-width: 150px;
-
-    font-size: 14px;
-}
-
 #loadingText {
     width: 100%;
     height: 60px;
@@ -253,16 +195,6 @@ li {
     -webkit-transform: translateX(120%);
 }
 
-#btnFullscreen, #btnPerf, #btnFiles {
-     -webkit-transition: -webkit-transform 0.15s ease-in-out;
-     transition: transform 0.15s ease-in-out;
-}
-
-#btnFullscreen:hover, #btnPerf:hover, #btnFiles:hover {
-    -webkit-transform: scale(0.9);
-    transform: scale(0.9);
-}
-
 #errorZone {
     display:none;
     position: absolute;

+ 7 - 21
sandbox/index.html

@@ -40,31 +40,17 @@
     <canvas id="renderCanvas"></canvas>
     <div id="logo">
     </div>
-    <div id="help01" class="help">
-        <span class="helpText">Press this button to open your assets' files</span>
-        <img id="helpArrow" src="./Assets/FlecheTuto.png" />
-    </div>
-    <div id="help02" class="help2">
-        <span class="helpText">Or directly drag'n'drop your files (in .babylon, .gltf, .glb, .obj format) in the browser</span>
-    </div>
     <div id="footer" class="footer">
         <div class="footerLeft">
-            Powered by <a href="http://www.babylonjs.com/" target="_blank">Babylon.js</a><br />
         </div>
         <div class="footerRight">
-            <ul>
-                <li id="btnFullscreen">
-                    <img src="./Assets/BtnFullscreen.png" alt="Switch the scene to full screen" title="Switch the scene to full screen" />
-                </li>
-                <li id="btnPerf">
-                    <img src="./Assets/BtnPerf.png" alt="Display inspector" title="Display inspector" />
-                </li>
-                <li id="btnFiles">
-                    <div class="custom-upload" title="Open your scene from your hard drive (.babylon, .gltf, .glb, .obj)">
-                        <input type="file" id="files" multiple />
-                    </div>
-                </li>
-            </ul>
+            <a href="#" id="btnFullscreen" class="hidden"><img src="./Assets/Icon_Fullscreen.svg" alt="Switch the scene to full screen" title="Switch the scene to full screen" /></a> 
+            <a href="#" id="btnInspector" class="hidden"><img src="./Assets/Icon_EditModel.svg" alt="Display inspector" title="Display inspector" /></i></a> 
+            <a href="#">
+                <div class="custom-upload" title="Open your scene from your hard drive (.babylon, .gltf, .glb, .obj)">
+                    <input type="file" id="files" multiple />
+                </div>
+            </a>
         </div>
     </div>
     <div id="errorZone"></div>

+ 8 - 24
sandbox/index.js

@@ -35,28 +35,24 @@ if (BABYLON.Engine.isSupported()) {
     var htmlInput = document.getElementById("files");
     var footer = document.getElementById("footer");
     var btnFullScreen = document.getElementById("btnFullscreen");
-    var btnPerf = document.getElementById("btnPerf");
-    var help01 = document.getElementById("help01");
-    var help02 = document.getElementById("help02");
+    var btnInspector = document.getElementById("btnInspector");
     var errorZone = document.getElementById("errorZone");
     var filesInput;
-    var currentHelpCounter;
     var currentScene;
     var currentSkybox;
     var enableDebugLayer = false;
     var currentPluginName;
     var skyboxPath = "Assets/environment.dds";
 
+    btnFullScreen.classList.add("hidden");
+    btnInspector.classList.add("hidden");
+
     canvas.addEventListener("contextmenu", function (evt) {
         evt.preventDefault();
     }, false);
 
-    currentHelpCounter = localStorage.getItem("helpcounter");
-
     BABYLON.Engine.ShadersRepository = "/src/Shaders/";
 
-    if (!currentHelpCounter) currentHelpCounter = 0;
-
     // Setting up some GLTF values
     BABYLON.GLTFFileLoader.IncrementalLoading = false;
     BABYLON.SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
@@ -87,6 +83,9 @@ if (BABYLON.Engine.isSupported()) {
         // Clear the error
         errorZone.style.display = 'none';
 
+        btnFullScreen.classList.remove("hidden");
+        btnInspector.classList.remove("hidden");        
+
         currentScene = babylonScene;
         document.title = "BabylonJS - " + sceneFile.name;
         // Fix for IE, otherwise it will change the default filter for files selection after first use
@@ -225,27 +224,12 @@ if (BABYLON.Engine.isSupported()) {
     if (kiosk) {
         footer.style.display = "none";
     }
-    else {
-        // The help tips will be displayed only 5 times
-        if (currentHelpCounter < 5) {
-            help01.className = "help shown";
-
-            setTimeout(function () {
-                help01.className = "help";
-                help02.className = "help2 shown";
-                setTimeout(function () {
-                    help02.className = "help2";
-                    localStorage.setItem("helpcounter", currentHelpCounter + 1);
-                }, 5000);
-            }, 5000);
-        }
-    }
 
     btnFullScreen.addEventListener('click', function () {
         engine.switchFullscreen(true);
     }, false);
 
-    btnPerf.addEventListener('click', function () {
+    btnInspector.addEventListener('click', function () {
         if (currentScene) {
             if (!enableDebugLayer) {
                 currentScene.debugLayer.show();

+ 1 - 1
src/Animations/babylon.runtimeAnimation.ts

@@ -278,7 +278,7 @@
                 if (!this._originalValue) {
                     let originalValue: any;
 
-                    if (destination.getRestPose) { // For bones
+                    if (destination.getRestPose && path === "_matrix") { // For bones
                         originalValue = destination.getRestPose();
                     } else {
                         originalValue = destination[path];

+ 6 - 1
src/Engine/babylon.engine.ts

@@ -726,7 +726,7 @@
          * Returns the current version of the framework
          */
         public static get Version(): string {
-            return "3.2.0-beta.5";
+            return "3.2.0-rc.1";
         }
 
         // Updatable statics so stick with vars here
@@ -782,6 +782,11 @@
          **/
         public enableOfflineSupport = false;
 
+        /** 
+         * Gets or sets a boolean to enable/disable checking manifest if IndexedDB support is enabled (Babylon.js will always consider the database is up to date)
+         **/
+        public disableManifestCheck = false;        
+
         /**
          * Gets the list of created scenes
          */

+ 3 - 2
src/Loading/babylon.sceneLoader.ts

@@ -309,7 +309,8 @@
             }
 
             if (rootUrl.indexOf("file:") === -1) {
-                let canUseOfflineSupport = scene.getEngine().enableOfflineSupport;
+                let engine = scene.getEngine();
+                let canUseOfflineSupport = engine.enableOfflineSupport;
                 if (canUseOfflineSupport) {
                     // Also check for exceptions
                     let exceptionFound = false;
@@ -325,7 +326,7 @@
 
                 if (canUseOfflineSupport) {
                     // Checking if a manifest file has been set for this scene and if offline mode has been requested
-                    database = new Database(rootUrl + sceneFilename, manifestChecked);
+                    database = new Database(rootUrl + sceneFilename, manifestChecked, engine.disableManifestCheck);
                 }
                 else {
                     manifestChecked();

+ 2 - 2
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -132,7 +132,7 @@
 
         public FORCENORMALFORWARD = false;
 
-        public GEOMETRYAA = false;
+        public SPECULARAA = false;
 
         public UNLIT = false;
 
@@ -1211,7 +1211,7 @@
                 defines.ALPHAFRESNEL = this._useAlphaFresnel || this._useLinearAlphaFresnel;
                 defines.LINEARALPHAFRESNEL = this._useLinearAlphaFresnel;
 
-                defines.GEOMETRYAA = scene.getEngine().getCaps().standardDerivatives && this._enableSpecularAntiAliasing;
+                defines.SPECULARAA = scene.getEngine().getCaps().standardDerivatives && this._enableSpecularAntiAliasing;
             }
 
             if (defines._areImageProcessingDirty) {

+ 4 - 2
src/Materials/Textures/babylon.videoTexture.ts

@@ -32,6 +32,7 @@
 
         private _generateMipMaps: boolean;
         private _engine: Engine;
+        private _stillImageCaptured = false;
 
         /**
          * Creates a video texture.
@@ -141,8 +142,8 @@
             );
 
             this._texture.isReady = true;
-            this._updateInternalTexture();
 
+            this._updateInternalTexture();
             if (this._onLoadObservable && this._onLoadObservable.hasObservers()) {
                 this.onLoadObservable.notifyObservers(this);
             }
@@ -183,9 +184,10 @@
             if (!isVisible) {
                 return;
             }
-            if (this.video.paused) {
+            if (this.video.paused && this._stillImageCaptured) {
                 return;
             }
+            this._stillImageCaptured = true;
             this._updateInternalTexture();
         }
 

+ 3 - 5
src/Shaders/ShadersInclude/pbrFunctions.fx

@@ -137,11 +137,9 @@ float environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped)
     return clamp(square(temp) - 1.0 + ambientOcclusion, 0.0, 1.0);
 }
 
-float environmentHorizonOcclusion(vec3 reflection, vec3 normal) {
-	// http://marmosetco.tumblr.com/post/81245981087
-#ifdef REFLECTIONMAP_OPPOSITEZ
-    reflection.z *= -1.0;
-#endif
+float environmentHorizonOcclusion(vec3 view, vec3 normal) {
+    // http://marmosetco.tumblr.com/post/81245981087
+    vec3 reflection = reflect(view, normal);
     float temp = clamp( 1.0 + 1.1 * dot(reflection, normal), 0.0, 1.0);
     return square(temp);
 }

+ 6 - 6
src/Shaders/pbr.fragment.fx

@@ -1,4 +1,4 @@
-#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(GEOMETRYAA)
+#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(SPECULARAA)
 #extension GL_OES_standard_derivatives : enable
 #endif
 
@@ -226,7 +226,9 @@ void main(void) {
     vec3 normalW = normalize(cross(dFdx(vPositionW), dFdy(vPositionW))) * vEyePosition.w;
 #endif
 
-#ifdef GEOMETRYAA
+#include<bumpFragment>
+
+#ifdef SPECULARAA
     vec3 nDfdx = dFdx(normalW.xyz);
     vec3 nDfdy = dFdy(normalW.xyz);
     float slopeSquare = max(dot(nDfdx, nDfdx), dot(nDfdy, nDfdy));
@@ -238,8 +240,6 @@ void main(void) {
     float geometricRoughnessFactor = 0.;
 #endif
 
-#include<bumpFragment>
-
 #if defined(FORCENORMALFORWARD) && defined(NORMAL)
     vec3 faceNormal = normalize(cross(dFdx(vPositionW), dFdy(vPositionW))) * vEyePosition.w;
     #if defined(TWOSIDEDLIGHTING)
@@ -434,7 +434,7 @@ void main(void) {
         float NdotV = clamp(NdotVUnclamped,0., 1.) + 0.00001;
         float alphaG = convertRoughnessToAverageSlope(roughness);
 
-        #ifdef GEOMETRYAA
+        #ifdef SPECULARAA
             // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
             // 75% accounts a bit for the bigger tail linked to Gaussian Filtering.
             alphaG += (0.75 * geometricAlphaGFactor);
@@ -660,7 +660,7 @@ void main(void) {
         #ifdef HORIZONOCCLUSION
             #ifdef BUMP
                 #ifdef REFLECTIONMAP_3D
-                    float eho = environmentHorizonOcclusion(reflectionCoords, normalW);
+                    float eho = environmentHorizonOcclusion(-viewDirectionW, normalW);
                     specularEnvironmentReflectance *= eho;
                 #endif
             #endif

+ 56 - 9
src/Tools/babylon.database.ts

@@ -1,4 +1,8 @@
 module BABYLON {
+    /**
+     * Class used to enable access to IndexedDB
+     * @see @https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
+     */
     export class Database {
         private callbackManifestChecked: (check: boolean) => any;
         private currentSceneUrl: string;
@@ -13,20 +17,35 @@ module BABYLON {
         // Handling various flavors of prefixed version of IndexedDB
         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;
+
+        /** Gets a boolean indicating if Database storate is enabled */
         static IDBStorageEnabled = true;
 
+        /**
+         * Gets a boolean indicating if scene must be saved in the database
+         */
         public get enableSceneOffline(): boolean {
             return this._enableSceneOffline;
         }
 
+        /**
+         * Gets a boolean indicating if textures must be saved in the database
+         */
         public get enableTexturesOffline(): boolean {
             return this._enableTexturesOffline;
         }
 
-        constructor(urlToScene: string, callbackManifestChecked: (checked: boolean) => any) {
+        /**
+         * Creates a new Database
+         * @param urlToScene defines the url to load the scene
+         * @param callbackManifestChecked defines the callback to use when manifest is checked
+         * @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.currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
             this.db = null;
             this._enableSceneOffline = false;
             this._enableTexturesOffline = false;
@@ -37,11 +56,21 @@ module BABYLON {
             if (!Database.IDBStorageEnabled) {
                 this.callbackManifestChecked(true);
             } else {
-                this.checkManifestFile();
+                if (disableManifestCheck) {
+                    this._enableSceneOffline = true;
+                    this._enableTexturesOffline = true;
+                    this.manifestVersionFound = 1;
+                    Tools.SetImmediate(() => {
+                        this.callbackManifestChecked(true);
+                    });
+                }
+                else {
+                    this._checkManifestFile();
+                }
             }
         }
 
-        static parseURL = (url: string) => {
+        private static _ParseURL = (url: string) => {
             var a = document.createElement('a');
             a.href = url;
             var urlWithoutHash = url.substring(0, url.lastIndexOf("#"));
@@ -50,16 +79,16 @@ module BABYLON {
             return absLocation;
         }
 
-        static ReturnFullUrlLocation = (url: string): string => {
+        private static _ReturnFullUrlLocation = (url: string): string => {
             if (url.indexOf("http:/") === -1 && url.indexOf("https:/") === -1) {
-                return (Database.parseURL(window.location.href) + url);
+                return (Database._ParseURL(window.location.href) + url);
             }
             else {
                 return url;
             }
         }
 
-        public checkManifestFile() {
+        private _checkManifestFile() {
             var noManifestFile = () => {
                 this._enableSceneOffline = false;
                 this._enableTexturesOffline = false;
@@ -123,6 +152,11 @@ module BABYLON {
             }
         }
 
+        /**
+         * Open the database and make it available
+         * @param successCallback defines the callback to call on success
+         * @param errorCallback defines the callback to call on error
+         */
         public openAsync(successCallback: () => void, errorCallback: () => void) {
             let handleError = () => {
                 this.isSupported = false;
@@ -182,8 +216,13 @@ module BABYLON {
             }
         }
 
+        /**
+         * Loads an image from the database
+         * @param url defines the url to load from
+         * @param image defines the target DOM image
+         */
         public loadImageFromDB(url: string, image: HTMLImageElement) {
-            var completeURL = Database.ReturnFullUrlLocation(url);
+            var completeURL = Database._ReturnFullUrlLocation(url);
 
             var saveAndLoadImage = () => {
                 if (!this.hasReachedQuota && this.db !== null) {
@@ -442,8 +481,16 @@ module BABYLON {
             }
         }
 
+        /**
+         * Loads a file from database
+         * @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
+         */
         public loadFileFromDB(url: string, sceneLoaded: (data: any) => void, progressCallBack?: (data: any) => void, errorCallback?: () => void, useArrayBuffer?: boolean) {
-            var completeUrl = Database.ReturnFullUrlLocation(url);
+            var completeUrl = Database._ReturnFullUrlLocation(url);
 
             var saveAndLoadFile = () => {
                 // the scene is not yet in the DB, let's try to save it

+ 22 - 2
src/Tools/babylon.promise.ts

@@ -15,13 +15,26 @@ module BABYLON {
 
     class InternalPromise<T> {
         private _state = PromiseStates.Pending;
-        private _result?: Nullable<T>;
+        private _resultValue?: Nullable<T>;
         private _reason: any;
         private _children = new Array<InternalPromise<T>>();
+        private _parent: Nullable<InternalPromise<T>>;
         private _onFulfilled?: (fulfillment?: Nullable<T>) => Nullable<InternalPromise<T>> | T;
         private _onRejected?: (reason: any) => void;
         private _rejectWasConsumed = false;
 
+        private get _result(): Nullable<T> | undefined {
+            return this._resultValue;
+        }
+
+        private set _result(value: Nullable<T> | undefined) {
+            this._resultValue = value;
+
+            if (this._parent && this._parent._result === undefined) {
+                this._parent._result = value;
+            }
+        }
+
         public constructor(resolver?: (
             resolve: (value?: Nullable<T>) => void,
             reject: (reason: any) => void
@@ -53,6 +66,7 @@ module BABYLON {
 
             // Composition
             this._children.push(newPromise);
+            newPromise._parent = this;
 
             if (this._state !== PromiseStates.Pending) {
                 Tools.SetImmediate(() => {
@@ -63,6 +77,7 @@ module BABYLON {
                             if ((<InternalPromise<T>>returnedValue)._state !== undefined) {
                                 let returnedPromise = returnedValue as InternalPromise<T>;
                                 newPromise._children.push(returnedPromise);
+                                returnedPromise._parent = newPromise;
                                 newPromise = returnedPromise;
                             } else {
                                 newPromise._result = (<T>returnedValue);
@@ -80,6 +95,10 @@ module BABYLON {
         private _moveChildren(children: InternalPromise<T>[]): void {
             this._children.push(...children.splice(0, children.length));
 
+            this._children.forEach(child => {
+                child._parent = this;
+            });
+
             if (this._state === PromiseStates.Fulfilled) {
                 for (var child of this._children) {
                     child._resolve(this._result);
@@ -104,8 +123,9 @@ module BABYLON {
                     if ((<InternalPromise<T>>returnedValue)._state !== undefined) {
                         // Transmit children
                         let returnedPromise = returnedValue as InternalPromise<T>;
-
+                        returnedPromise._parent = this;
                         returnedPromise._moveChildren(this._children);
+
                         value = returnedPromise._result;
                     } else {
                         value = <T>returnedValue;

+ 29 - 0
tests/unit/babylon/src/Tools/babylon.promise.tests.ts

@@ -217,6 +217,35 @@ describe('Babylon.Promise', function () {
                     }
                 });
         });
+
+        it('should correctly handle then multiple times', (done) => {
+            var promise = Promise.resolve().then(function () {
+                return new Promise(function (resolve) {
+                    setTimeout(function () {
+                        resolve(123);
+                    }, 100);
+                });
+            });
+            
+            promise.then(function (result1) {
+                try {
+                    result1.should.be.equal(123);
+                }
+                catch(error) {
+                    done(error);
+                }
+                return promise.then(function (result2) {
+                    try {
+                        result2.should.be.equal(123);
+                        done();
+                    }
+                    catch(error) {
+                        done(error);
+                    }
+                });
+            });    
+        });        
+
     });
 
     describe('#Multiple children', () => {