Explorar el Código

Merge branch 'newinspector' of https://github.com/BabylonJS/Babylon.js into newinspector

David Catuhe hace 6 años
padre
commit
d101d8d1ff
Se han modificado 41 ficheros con 13993 adiciones y 23392 borrados
  1. 7039 7009
      Playground/babylon.d.txt
  2. 6259 6251
      dist/preview release/babylon.d.ts
  3. 1 1
      dist/preview release/babylon.js
  4. 49 0
      dist/preview release/babylon.max.js
  5. 49 0
      dist/preview release/babylon.no-module.max.js
  6. 1 1
      dist/preview release/babylon.worker.js
  7. 49 0
      dist/preview release/es6.js
  8. 4 2
      dist/preview release/gui/babylon.gui.d.ts
  9. 1 1
      dist/preview release/gui/babylon.gui.js
  10. 1 1
      dist/preview release/gui/babylon.gui.min.js
  11. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  12. 8 4
      dist/preview release/gui/babylon.gui.module.d.ts
  13. 47 9797
      dist/preview release/inspector/babylon.inspector.bundle.js
  14. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js.map
  15. 28 29
      dist/preview release/inspector/babylon.inspector.d.ts
  16. 58 60
      dist/preview release/inspector/babylon.inspector.module.d.ts
  17. 8 0
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  18. 58 35
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  19. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  20. 8 0
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  21. 58 35
      dist/preview release/loaders/babylon.glTFFileLoader.js
  22. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  23. 8 0
      dist/preview release/loaders/babylonjs.loaders.d.ts
  24. 58 35
      dist/preview release/loaders/babylonjs.loaders.js
  25. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  26. 8 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  27. 5 19
      dist/preview release/viewer/babylon.viewer.d.ts
  28. 1 1
      dist/preview release/viewer/babylon.viewer.js
  29. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  30. 5 22
      dist/preview release/viewer/babylon.viewer.module.d.ts
  31. 3 1
      dist/preview release/what's new.md
  32. 35 14
      gui/src/2D/controls/inputText.ts
  33. 5 8
      inspector/src/Inspector.ts
  34. 18 11
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx
  35. 2 0
      loaders/src/glTF/2.0/Extensions/KHR_lights_punctual.ts
  36. 2 2
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  37. 1 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts
  38. 56 32
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  39. 6 0
      src/Materials/Textures/babylon.baseTexture.ts
  40. 43 0
      src/babylon.assetContainer.ts
  41. 4 13
      tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 7039 - 7009
Playground/babylon.d.txt


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 6259 - 6251
dist/preview release/babylon.d.ts


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/babylon.js


+ 49 - 0
dist/preview release/babylon.max.js

@@ -30524,6 +30524,48 @@ var BABYLON;
                 component.removeFromContainer(this);
             }
         };
+        /**
+         * Disposes all the assets in the container
+         */
+        AssetContainer.prototype.dispose = function () {
+            this.cameras.forEach(function (o) {
+                o.dispose();
+            });
+            this.lights.forEach(function (o) {
+                o.dispose();
+            });
+            this.meshes.forEach(function (o) {
+                o.dispose();
+            });
+            this.skeletons.forEach(function (o) {
+                o.dispose();
+            });
+            this.animationGroups.forEach(function (o) {
+                o.dispose();
+            });
+            this.multiMaterials.forEach(function (o) {
+                o.dispose();
+            });
+            this.materials.forEach(function (o) {
+                o.dispose();
+            });
+            this.geometries.forEach(function (o) {
+                o.dispose();
+            });
+            this.transformNodes.forEach(function (o) {
+                o.dispose();
+            });
+            this.actionManagers.forEach(function (o) {
+                o.dispose();
+            });
+            this.textures.forEach(function (o) {
+                o.dispose();
+            });
+            for (var _i = 0, _a = this.scene._serializableComponents; _i < _a.length; _i++) {
+                var component = _a[_i];
+                component.dispose();
+            }
+        };
         AssetContainer.prototype._moveAssets = function (sourceAssets, targetAssets, keepAssets) {
             if (!sourceAssets) {
                 return;
@@ -31499,6 +31541,10 @@ var BABYLON;
          * @param scene Define the scene the texture blongs to
          */
         function BaseTexture(scene) {
+            /**
+             * Gets or sets an object used to store user defined information.
+             */
+            this.metadata = null;
             this._hasAlpha = false;
             /**
              * Defines if the alpha value should be determined via the rgb values.
@@ -32083,6 +32129,9 @@ var BABYLON;
             BABYLON.serialize()
         ], BaseTexture.prototype, "name", void 0);
         __decorate([
+            BABYLON.serialize()
+        ], BaseTexture.prototype, "metadata", void 0);
+        __decorate([
             BABYLON.serialize("hasAlpha")
         ], BaseTexture.prototype, "_hasAlpha", void 0);
         __decorate([

+ 49 - 0
dist/preview release/babylon.no-module.max.js

@@ -30491,6 +30491,48 @@ var BABYLON;
                 component.removeFromContainer(this);
             }
         };
+        /**
+         * Disposes all the assets in the container
+         */
+        AssetContainer.prototype.dispose = function () {
+            this.cameras.forEach(function (o) {
+                o.dispose();
+            });
+            this.lights.forEach(function (o) {
+                o.dispose();
+            });
+            this.meshes.forEach(function (o) {
+                o.dispose();
+            });
+            this.skeletons.forEach(function (o) {
+                o.dispose();
+            });
+            this.animationGroups.forEach(function (o) {
+                o.dispose();
+            });
+            this.multiMaterials.forEach(function (o) {
+                o.dispose();
+            });
+            this.materials.forEach(function (o) {
+                o.dispose();
+            });
+            this.geometries.forEach(function (o) {
+                o.dispose();
+            });
+            this.transformNodes.forEach(function (o) {
+                o.dispose();
+            });
+            this.actionManagers.forEach(function (o) {
+                o.dispose();
+            });
+            this.textures.forEach(function (o) {
+                o.dispose();
+            });
+            for (var _i = 0, _a = this.scene._serializableComponents; _i < _a.length; _i++) {
+                var component = _a[_i];
+                component.dispose();
+            }
+        };
         AssetContainer.prototype._moveAssets = function (sourceAssets, targetAssets, keepAssets) {
             if (!sourceAssets) {
                 return;
@@ -31466,6 +31508,10 @@ var BABYLON;
          * @param scene Define the scene the texture blongs to
          */
         function BaseTexture(scene) {
+            /**
+             * Gets or sets an object used to store user defined information.
+             */
+            this.metadata = null;
             this._hasAlpha = false;
             /**
              * Defines if the alpha value should be determined via the rgb values.
@@ -32050,6 +32096,9 @@ var BABYLON;
             BABYLON.serialize()
         ], BaseTexture.prototype, "name", void 0);
         __decorate([
+            BABYLON.serialize()
+        ], BaseTexture.prototype, "metadata", void 0);
+        __decorate([
             BABYLON.serialize("hasAlpha")
         ], BaseTexture.prototype, "_hasAlpha", void 0);
         __decorate([

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/babylon.worker.js


+ 49 - 0
dist/preview release/es6.js

@@ -30491,6 +30491,48 @@ var BABYLON;
                 component.removeFromContainer(this);
             }
         };
+        /**
+         * Disposes all the assets in the container
+         */
+        AssetContainer.prototype.dispose = function () {
+            this.cameras.forEach(function (o) {
+                o.dispose();
+            });
+            this.lights.forEach(function (o) {
+                o.dispose();
+            });
+            this.meshes.forEach(function (o) {
+                o.dispose();
+            });
+            this.skeletons.forEach(function (o) {
+                o.dispose();
+            });
+            this.animationGroups.forEach(function (o) {
+                o.dispose();
+            });
+            this.multiMaterials.forEach(function (o) {
+                o.dispose();
+            });
+            this.materials.forEach(function (o) {
+                o.dispose();
+            });
+            this.geometries.forEach(function (o) {
+                o.dispose();
+            });
+            this.transformNodes.forEach(function (o) {
+                o.dispose();
+            });
+            this.actionManagers.forEach(function (o) {
+                o.dispose();
+            });
+            this.textures.forEach(function (o) {
+                o.dispose();
+            });
+            for (var _i = 0, _a = this.scene._serializableComponents; _i < _a.length; _i++) {
+                var component = _a[_i];
+                component.dispose();
+            }
+        };
         AssetContainer.prototype._moveAssets = function (sourceAssets, targetAssets, keepAssets) {
             if (!sourceAssets) {
                 return;
@@ -31466,6 +31508,10 @@ var BABYLON;
          * @param scene Define the scene the texture blongs to
          */
         function BaseTexture(scene) {
+            /**
+             * Gets or sets an object used to store user defined information.
+             */
+            this.metadata = null;
             this._hasAlpha = false;
             /**
              * Defines if the alpha value should be determined via the rgb values.
@@ -32050,6 +32096,9 @@ var BABYLON;
             BABYLON.serialize()
         ], BaseTexture.prototype, "name", void 0);
         __decorate([
+            BABYLON.serialize()
+        ], BaseTexture.prototype, "metadata", void 0);
+        __decorate([
             BABYLON.serialize("hasAlpha")
         ], BaseTexture.prototype, "_hasAlpha", void 0);
         __decorate([

+ 4 - 2
dist/preview release/gui/babylon.gui.d.ts

@@ -1473,9 +1473,11 @@ declare module BABYLON.GUI {
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
-            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            /** Gets or sets the text highlighter transparency; default: 0.4 */
             highligherOpacity: number;
-            /** Gets and sets the text hightlight color */
+            /** Gets or sets a boolean indicating whether to select complete text by default on input focus */
+            onFocusSelectAll: boolean;
+            /** Gets or sets the text hightlight color */
             textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/gui/babylon.gui.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


+ 8 - 4
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1598,9 +1598,11 @@ declare module 'babylonjs-gui/2D/controls/inputText' {
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
-            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            /** Gets or sets the text highlighter transparency; default: 0.4 */
             highligherOpacity: number;
-            /** Gets and sets the text hightlight color */
+            /** Gets or sets a boolean indicating whether to select complete text by default on input focus */
+            onFocusSelectAll: boolean;
+            /** Gets or sets the text hightlight color */
             textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;
@@ -4458,9 +4460,11 @@ declare module BABYLON.GUI {
             maxWidth: string | number;
             /** Gets the maximum width allowed by the control in pixels */
             readonly maxWidthInPixels: number;
-            /** Gets and sets the text highlighter transparency; default: 0.4 */
+            /** Gets or sets the text highlighter transparency; default: 0.4 */
             highligherOpacity: number;
-            /** Gets and sets the text hightlight color */
+            /** Gets or sets a boolean indicating whether to select complete text by default on input focus */
+            onFocusSelectAll: boolean;
+            /** Gets or sets the text hightlight color */
             textHighlightColor: string;
             /** Gets or sets control margin */
             margin: string;

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 47 - 9797
dist/preview release/inspector/babylon.inspector.bundle.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


+ 28 - 29
dist/preview release/inspector/babylon.inspector.d.ts

@@ -3,35 +3,34 @@
 //   ../../../../Tools/Gulp/babylonjs
 declare module INSPECTOR {
 }
-export interface IExtensibilityOption {
-    label: string;
-    action: (entity: any) => void;
-}
-export interface IExtensibilityGroup {
-    predicate: (entity: any) => boolean;
-    entries: IExtensibilityOption[];
-}
-export interface IInspectorOptions {
-    overlay?: boolean;
-    sceneExplorerRoot?: HTMLElement;
-    actionTabsRoot?: HTMLElement;
-    embedHostRoot?: HTMLElement;
-    showExplorer?: boolean;
-    showInspector?: boolean;
-    explorerWidth?: string;
-    inspectorWidth?: string;
-    embedHostWidth?: string;
-    embedMode?: boolean;
-    handleResize?: boolean;
-    enablePopup?: boolean;
-    explorerExtensibility?: IExtensibilityGroup[];
-}
-export declare class Inspector {
-    static OnSelectionChangeObservable: BABYLON.Observable<string>;
-    static OnPropertyChangedObservable: BABYLON.Observable<PropertyChangedEvent>;
-    static readonly IsVisible: boolean;
-    static Show(scene: BABYLON.Scene, userOptions: Partial<IInspectorOptions>): void;
-    static Hide(): void;
+declare module INSPECTOR {
+    export interface IExtensibilityOption {
+        label: string;
+        action: (entity: any) => void;
+    }
+    export interface IExtensibilityGroup {
+        predicate: (entity: any) => boolean;
+        entries: IExtensibilityOption[];
+    }
+    export interface IInspectorOptions {
+        overlay?: boolean;
+        sceneExplorerRoot?: HTMLElement;
+        actionTabsRoot?: HTMLElement;
+        embedHostRoot?: HTMLElement;
+        showExplorer?: boolean;
+        showInspector?: boolean;
+        embedMode?: boolean;
+        handleResize?: boolean;
+        enablePopup?: boolean;
+        explorerExtensibility?: IExtensibilityGroup[];
+    }
+    export class Inspector {
+        static OnSelectionChangeObservable: BABYLON.Observable<string>;
+        static OnPropertyChangedObservable: BABYLON.Observable<PropertyChangedEvent>;
+        static readonly IsVisible: boolean;
+        static Show(scene: BABYLON.Scene, userOptions: Partial<IInspectorOptions>): void;
+        static Hide(): void;
+    }
 }
 declare module INSPECTOR {
     export class PropertyChangedEvent {

+ 58 - 60
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -6,37 +6,36 @@ declare module 'babylonjs-inspector' {
     export * from "babylonjs-inspector/inspector";
 }
 
-import { Scene, Observable } from "babylonjs";
-import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
-export interface IExtensibilityOption {
-    label: string;
-    action: (entity: any) => void;
-}
-export interface IExtensibilityGroup {
-    predicate: (entity: any) => boolean;
-    entries: IExtensibilityOption[];
-}
-export interface IInspectorOptions {
-    overlay?: boolean;
-    sceneExplorerRoot?: HTMLElement;
-    actionTabsRoot?: HTMLElement;
-    embedHostRoot?: HTMLElement;
-    showExplorer?: boolean;
-    showInspector?: boolean;
-    explorerWidth?: string;
-    inspectorWidth?: string;
-    embedHostWidth?: string;
-    embedMode?: boolean;
-    handleResize?: boolean;
-    enablePopup?: boolean;
-    explorerExtensibility?: IExtensibilityGroup[];
-}
-export declare class Inspector {
-    static OnSelectionChangeObservable: Observable<string>;
-    static OnPropertyChangedObservable: Observable<PropertyChangedEvent>;
-    static readonly IsVisible: boolean;
-    static Show(scene: Scene, userOptions: Partial<IInspectorOptions>): void;
-    static Hide(): void;
+declare module 'babylonjs-inspector/inspector' {
+    import { Scene, Observable } from "babylonjs";
+    import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
+    export interface IExtensibilityOption {
+        label: string;
+        action: (entity: any) => void;
+    }
+    export interface IExtensibilityGroup {
+        predicate: (entity: any) => boolean;
+        entries: IExtensibilityOption[];
+    }
+    export interface IInspectorOptions {
+        overlay?: boolean;
+        sceneExplorerRoot?: HTMLElement;
+        actionTabsRoot?: HTMLElement;
+        embedHostRoot?: HTMLElement;
+        showExplorer?: boolean;
+        showInspector?: boolean;
+        embedMode?: boolean;
+        handleResize?: boolean;
+        enablePopup?: boolean;
+        explorerExtensibility?: IExtensibilityGroup[];
+    }
+    export class Inspector {
+        static OnSelectionChangeObservable: Observable<string>;
+        static OnPropertyChangedObservable: Observable<PropertyChangedEvent>;
+        static readonly IsVisible: boolean;
+        static Show(scene: Scene, userOptions: Partial<IInspectorOptions>): void;
+        static Hide(): void;
+    }
 }
 
 declare module 'babylonjs-inspector/components/propertyChangedEvent' {
@@ -54,35 +53,34 @@ declare module 'babylonjs-inspector/components/propertyChangedEvent' {
 //   ../../../../Tools/Gulp/babylonjs
 declare module INSPECTOR {
 }
-export interface IExtensibilityOption {
-    label: string;
-    action: (entity: any) => void;
-}
-export interface IExtensibilityGroup {
-    predicate: (entity: any) => boolean;
-    entries: IExtensibilityOption[];
-}
-export interface IInspectorOptions {
-    overlay?: boolean;
-    sceneExplorerRoot?: HTMLElement;
-    actionTabsRoot?: HTMLElement;
-    embedHostRoot?: HTMLElement;
-    showExplorer?: boolean;
-    showInspector?: boolean;
-    explorerWidth?: string;
-    inspectorWidth?: string;
-    embedHostWidth?: string;
-    embedMode?: boolean;
-    handleResize?: boolean;
-    enablePopup?: boolean;
-    explorerExtensibility?: IExtensibilityGroup[];
-}
-export declare class Inspector {
-    static OnSelectionChangeObservable: BABYLON.Observable<string>;
-    static OnPropertyChangedObservable: BABYLON.Observable<PropertyChangedEvent>;
-    static readonly IsVisible: boolean;
-    static Show(scene: BABYLON.Scene, userOptions: Partial<IInspectorOptions>): void;
-    static Hide(): void;
+declare module INSPECTOR {
+    export interface IExtensibilityOption {
+        label: string;
+        action: (entity: any) => void;
+    }
+    export interface IExtensibilityGroup {
+        predicate: (entity: any) => boolean;
+        entries: IExtensibilityOption[];
+    }
+    export interface IInspectorOptions {
+        overlay?: boolean;
+        sceneExplorerRoot?: HTMLElement;
+        actionTabsRoot?: HTMLElement;
+        embedHostRoot?: HTMLElement;
+        showExplorer?: boolean;
+        showInspector?: boolean;
+        embedMode?: boolean;
+        handleResize?: boolean;
+        enablePopup?: boolean;
+        explorerExtensibility?: IExtensibilityGroup[];
+    }
+    export class Inspector {
+        static OnSelectionChangeObservable: BABYLON.Observable<string>;
+        static OnPropertyChangedObservable: BABYLON.Observable<PropertyChangedEvent>;
+        static readonly IsVisible: boolean;
+        static Show(scene: BABYLON.Scene, userOptions: Partial<IInspectorOptions>): void;
+        static Hide(): void;
+    }
 }
 declare module INSPECTOR {
     export class PropertyChangedEvent {

+ 8 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -758,6 +758,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 58 - 35
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -941,11 +941,11 @@ var BABYLON;
                     _this._extensionsOnLoading();
                     var promises = new Array();
                     if (nodes) {
-                        promises.push(_this.loadSceneAsync("#/nodes", { nodes: nodes, index: -1 }));
+                        promises.push(_this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
                     }
                     else {
-                        var scene = ArrayItem.Get("#/scene", _this.gltf.scenes, _this.gltf.scene || 0);
-                        promises.push(_this.loadSceneAsync("#/scenes/" + scene.index, scene));
+                        var scene = ArrayItem.Get("/scene", _this.gltf.scenes, _this.gltf.scene || 0);
+                        promises.push(_this.loadSceneAsync("/scenes/" + scene.index, scene));
                     }
                     if (_this._parent.compileMaterials) {
                         promises.push(_this._compileMaterialsAsync());
@@ -1109,7 +1109,7 @@ var BABYLON;
                     for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) {
                         var index = _a[_i];
                         var node = ArrayItem.Get(context + "/nodes/" + index, this.gltf.nodes, index);
-                        promises.push(this.loadNodeAsync("#/nodes/" + node.index, node, function (babylonMesh) {
+                        promises.push(this.loadNodeAsync("/nodes/" + node.index, node, function (babylonMesh) {
                             babylonMesh.parent = _this._rootBabylonMesh;
                         }));
                     }
@@ -1217,17 +1217,18 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (node.name || ""));
                 var loadNode = function (babylonTransformNode) {
+                    GLTFLoader.AddPointerMetadata(babylonTransformNode, context);
                     GLTFLoader._LoadTransform(node, babylonTransformNode);
                     if (node.camera != undefined) {
                         var camera = ArrayItem.Get(context + "/camera", _this.gltf.cameras, node.camera);
-                        promises.push(_this.loadCameraAsync("#/cameras/" + camera.index, camera, function (babylonCamera) {
+                        promises.push(_this.loadCameraAsync("/cameras/" + camera.index, camera, function (babylonCamera) {
                             babylonCamera.parent = babylonTransformNode;
                         }));
                     }
                     if (node.children) {
                         var _loop_1 = function (index) {
                             var childNode = ArrayItem.Get(context + "/children/" + index, _this.gltf.nodes, index);
-                            promises.push(_this.loadNodeAsync("#/nodes/" + node.index, childNode, function (childBabylonMesh) {
+                            promises.push(_this.loadNodeAsync("/nodes/" + childNode.index, childNode, function (childBabylonMesh) {
                                 // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
                                 if (childNode.skin != undefined) {
                                     childBabylonMesh.parent = _this._rootBabylonMesh;
@@ -1250,7 +1251,7 @@ var BABYLON;
                 }
                 else {
                     var mesh = ArrayItem.Get(context + "/mesh", this.gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh.index, node, mesh, loadNode));
+                    promises.push(this._loadMeshAsync("/meshes/" + mesh.index, node, mesh, loadNode));
                 }
                 this.logClose();
                 return Promise.all(promises).then(function () {
@@ -1291,7 +1292,7 @@ var BABYLON;
                 }
                 if (node.skin != undefined) {
                     var skin = ArrayItem.Get(context + "/skin", this.gltf.skins, node.skin);
-                    promises.push(this._loadSkinAsync("#/skins/" + skin.index, node, skin));
+                    promises.push(this._loadSkinAsync("/skins/" + skin.index, node, skin));
                 }
                 assign(node._babylonTransformNode);
                 this.logClose();
@@ -1331,7 +1332,7 @@ var BABYLON;
                     }
                     else {
                         var material = ArrayItem.Get(context + "/material", this.gltf.materials, primitive.material);
-                        promises.push(this._loadMaterialAsync("#/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
+                        promises.push(this._loadMaterialAsync("/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
                             babylonMesh_1.material = babylonMaterial;
                         }));
                     }
@@ -1344,6 +1345,7 @@ var BABYLON;
                     }
                     babylonAbstractMesh = babylonMesh_1;
                 }
+                GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);
                 this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);
                 assign(babylonAbstractMesh);
                 this.logClose();
@@ -1368,7 +1370,7 @@ var BABYLON;
                 }
                 else {
                     var accessor = ArrayItem.Get(context + "/indices", this.gltf.accessors, primitive.indices);
-                    promises.push(this._loadIndicesAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(this._loadIndicesAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         babylonGeometry.setIndices(data);
                     }));
                 }
@@ -1381,7 +1383,7 @@ var BABYLON;
                         babylonMesh._delayInfo.push(kind);
                     }
                     var accessor = ArrayItem.Get(context + "/attributes/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadVertexAccessorAsync("#/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
+                    promises.push(_this._loadVertexAccessorAsync("/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
                         babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
                     }));
                     if (callback) {
@@ -1445,7 +1447,7 @@ var BABYLON;
                         return;
                     }
                     var accessor = ArrayItem.Get(context + "/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(_this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         setData(babylonVertexBuffer, data);
                     }));
                 };
@@ -1558,7 +1560,7 @@ var BABYLON;
                     return Promise.resolve(null);
                 }
                 var accessor = ArrayItem.Get(context + "/inverseBindMatrices", this.gltf.accessors, skin.inverseBindMatrices);
-                return this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor);
+                return this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor);
             };
             GLTFLoader.prototype._updateBoneMatrices = function (babylonSkeleton, inverseBindMatricesData) {
                 for (var _i = 0, _a = babylonSkeleton.bones; _i < _a.length; _i++) {
@@ -1627,8 +1629,9 @@ var BABYLON;
                         throw new Error(context + ": Invalid camera type (" + camera.type + ")");
                     }
                 }
-                assign(babylonCamera);
+                GLTFLoader.AddPointerMetadata(babylonCamera, context);
                 this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
+                assign(babylonCamera);
                 return Promise.all(promises).then(function () {
                     return babylonCamera;
                 });
@@ -1641,7 +1644,7 @@ var BABYLON;
                 var promises = new Array();
                 for (var index = 0; index < animations.length; index++) {
                     var animation = animations[index];
-                    promises.push(this.loadAnimationAsync("#/animations/" + animation.index, animation));
+                    promises.push(this.loadAnimationAsync("/animations/" + animation.index, animation));
                 }
                 return Promise.all(promises).then(function () { });
             };
@@ -1844,8 +1847,8 @@ var BABYLON;
                 var inputAccessor = ArrayItem.Get(context + "/input", this.gltf.accessors, sampler.input);
                 var outputAccessor = ArrayItem.Get(context + "/output", this.gltf.accessors, sampler.output);
                 sampler._data = Promise.all([
-                    this._loadFloatAccessorAsync("#/accessors/" + inputAccessor.index, inputAccessor),
-                    this._loadFloatAccessorAsync("#/accessors/" + outputAccessor.index, outputAccessor)
+                    this._loadFloatAccessorAsync("/accessors/" + inputAccessor.index, inputAccessor),
+                    this._loadFloatAccessorAsync("/accessors/" + outputAccessor.index, outputAccessor)
                 ]).then(function (_a) {
                     var inputData = _a[0], outputData = _a[1];
                     return {
@@ -1877,7 +1880,7 @@ var BABYLON;
                     return bufferView._data;
                 }
                 var buffer = ArrayItem.Get(context + "/buffer", this.gltf.buffers, bufferView.buffer);
-                bufferView._data = this._loadBufferAsync("#/buffers/" + buffer.index, buffer).then(function (data) {
+                bufferView._data = this._loadBufferAsync("/buffers/" + buffer.index, buffer).then(function (data) {
                     try {
                         return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                     }
@@ -1900,7 +1903,7 @@ var BABYLON;
                     return accessor._data;
                 }
                 var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
                 });
                 return accessor._data;
@@ -1921,7 +1924,7 @@ var BABYLON;
                 }
                 else {
                     var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                    accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                    accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                         return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
                     });
                 }
@@ -1931,8 +1934,8 @@ var BABYLON;
                         var indicesBufferView = ArrayItem.Get(context + "/sparse/indices/bufferView", _this.gltf.bufferViews, sparse_1.indices.bufferView);
                         var valuesBufferView = ArrayItem.Get(context + "/sparse/values/bufferView", _this.gltf.bufferViews, sparse_1.values.bufferView);
                         return Promise.all([
-                            _this.loadBufferViewAsync("#/bufferViews/" + indicesBufferView.index, indicesBufferView),
-                            _this.loadBufferViewAsync("#/bufferViews/" + valuesBufferView.index, valuesBufferView)
+                            _this.loadBufferViewAsync("/bufferViews/" + indicesBufferView.index, indicesBufferView),
+                            _this.loadBufferViewAsync("/bufferViews/" + valuesBufferView.index, valuesBufferView)
                         ]).then(function (_a) {
                             var indicesData = _a[0], valuesData = _a[1];
                             var indices = GLTFLoader._GetTypedArray(context + "/sparse/indices", sparse_1.indices.componentType, indicesData, sparse_1.indices.byteOffset, sparse_1.count);
@@ -1955,7 +1958,7 @@ var BABYLON;
                 if (bufferView._babylonBuffer) {
                     return bufferView._babylonBuffer;
                 }
-                bufferView._babylonBuffer = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                bufferView._babylonBuffer = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return new BABYLON.Buffer(_this.babylonScene.getEngine(), data, false);
                 });
                 return bufferView._babylonBuffer;
@@ -1966,14 +1969,14 @@ var BABYLON;
                     return accessor._babylonVertexBuffer;
                 }
                 if (accessor.sparse) {
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
                 // HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
                 else if (accessor.byteOffset && accessor.byteOffset % BABYLON.VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
                     BABYLON.Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
@@ -2003,11 +2006,13 @@ var BABYLON;
                     babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;
                     if (properties.baseColorTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Base Color)";
                             babylonMaterial.albedoTexture = texture;
                         }));
                     }
                     if (properties.metallicRoughnessTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/metallicRoughnessTexture", properties.metallicRoughnessTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Metallic Roughness)";
                             babylonMaterial.metallicTexture = texture;
                         }));
                         babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
@@ -2035,6 +2040,7 @@ var BABYLON;
                         promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial)
                     };
                     material._data[babylonDrawMode] = babylonData;
+                    GLTFLoader.AddPointerMetadata(babylonMaterial, context);
                     this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
                     this.logClose();
                 }
@@ -2075,7 +2081,8 @@ var BABYLON;
                     return extensionPromise;
                 }
                 var name = material.name || "material" + material.index;
-                return this._createDefaultMaterial(name, babylonDrawMode);
+                var babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
+                return babylonMaterial;
             };
             /**
              * Loads properties from a glTF material into a Babylon material.
@@ -2116,6 +2123,7 @@ var BABYLON;
                 }
                 if (material.normalTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/normalTexture", material.normalTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Normal)";
                         babylonMaterial.bumpTexture = texture;
                     }));
                     babylonMaterial.invertNormalMapX = !this.babylonScene.useRightHandedSystem;
@@ -2126,6 +2134,7 @@ var BABYLON;
                 }
                 if (material.occlusionTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/occlusionTexture", material.occlusionTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Occlusion)";
                         babylonMaterial.ambientTexture = texture;
                     }));
                     babylonMaterial.useAmbientInGrayScale = true;
@@ -2135,6 +2144,7 @@ var BABYLON;
                 }
                 if (material.emissiveTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/emissiveTexture", material.emissiveTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Emissive)";
                         babylonMaterial.emissiveTexture = texture;
                     }));
                 }
@@ -2186,6 +2196,7 @@ var BABYLON;
              * @returns A promise that resolves with the loaded Babylon texture when the load is complete
              */
             GLTFLoader.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) {
+                var _this = this;
                 if (assign === void 0) { assign = function () { }; }
                 var extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
                 if (extensionPromise) {
@@ -2193,8 +2204,10 @@ var BABYLON;
                 }
                 this.logOpen("" + context);
                 var texture = ArrayItem.Get(context + "/index", this.gltf.textures, textureInfo.index);
-                var promise = this._loadTextureAsync("#/textures/" + textureInfo.index, texture, function (babylonTexture) {
+                var promise = this._loadTextureAsync("/textures/" + textureInfo.index, texture, function (babylonTexture) {
                     babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
+                    GLTFLoader.AddPointerMetadata(babylonTexture, context);
+                    _this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                     assign(babylonTexture);
                 });
                 this.logClose();
@@ -2206,7 +2219,7 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (texture.name || ""));
                 var sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(context + "/sampler", this.gltf.samplers, texture.sampler));
-                var samplerData = this._loadSampler("#/samplers/" + sampler.index, sampler);
+                var samplerData = this._loadSampler("/samplers/" + sampler.index, sampler);
                 var deferred = new BABYLON.Deferred();
                 var babylonTexture = new BABYLON.Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, function () {
                     if (!_this._disposed) {
@@ -2218,17 +2231,15 @@ var BABYLON;
                     }
                 });
                 promises.push(deferred.promise);
-                babylonTexture.name = texture.name || "texture" + texture.index;
                 babylonTexture.wrapU = samplerData.wrapU;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
-                promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
+                promises.push(this.loadImageAsync("/images/" + image.index, image).then(function (data) {
                     var name = image.uri || _this._fileName + "#image" + image.index;
                     var dataUrl = "data:" + _this._uniqueRootUrl + name;
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);
-                this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                 this.logClose();
                 return Promise.all(promises).then(function () {
                     return babylonTexture;
@@ -2259,7 +2270,7 @@ var BABYLON;
                     }
                     else {
                         var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, image.bufferView);
-                        image._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView);
+                        image._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView);
                     }
                     this.logClose();
                 }
@@ -2339,6 +2350,17 @@ var BABYLON;
                 }
                 this._progressCallback(new BABYLON.SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
+            /**
+             * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+             * @param babylonObject the Babylon object with metadata
+             * @param pointer the JSON pointer
+             */
+            GLTFLoader.AddPointerMetadata = function (babylonObject, pointer) {
+                var metadata = (babylonObject.metadata = babylonObject.metadata || {});
+                var gltf = (metadata.gltf = metadata.gltf || {});
+                var pointers = (gltf.pointers = gltf.pointers || []);
+                pointers.push(pointer);
+            };
             GLTFLoader._GetTextureWrapMode = function (context, mode) {
                 // Set defaults if undefined
                 mode = mode == undefined ? 10497 /* REPEAT */ : mode;
@@ -3367,14 +3389,14 @@ var BABYLON;
                         babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;
                         if (properties.diffuseTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/diffuseTexture", properties.diffuseTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Diffuse)";
                                 babylonMaterial.albedoTexture = texture;
-                                return Promise.resolve();
                             }));
                         }
                         if (properties.specularGlossinessTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/specularGlossinessTexture", properties.specularGlossinessTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Specular Glossiness)";
                                 babylonMaterial.reflectivityTexture = texture;
-                                return Promise.resolve();
                             }));
                             babylonMaterial.reflectivityTexture.hasAlpha = true;
                             babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
@@ -3442,8 +3464,8 @@ var BABYLON;
                             }
                             if (properties.baseColorTexture) {
                                 promises.push(this._loader.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                                    texture.name = babylonMaterial.name + " (Base Color)";
                                     babylonMaterial.albedoTexture = texture;
-                                    return Promise.resolve();
                                 }));
                             }
                         }
@@ -3539,6 +3561,7 @@ var BABYLON;
                                 babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;
                                 babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;
                                 babylonLight.parent = babylonMesh;
+                                GLTF2.GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);
                                 assign(babylonMesh);
                             });
                         });

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 8 - 0
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -1320,6 +1320,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 58 - 35
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3149,11 +3149,11 @@ var BABYLON;
                     _this._extensionsOnLoading();
                     var promises = new Array();
                     if (nodes) {
-                        promises.push(_this.loadSceneAsync("#/nodes", { nodes: nodes, index: -1 }));
+                        promises.push(_this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
                     }
                     else {
-                        var scene = ArrayItem.Get("#/scene", _this.gltf.scenes, _this.gltf.scene || 0);
-                        promises.push(_this.loadSceneAsync("#/scenes/" + scene.index, scene));
+                        var scene = ArrayItem.Get("/scene", _this.gltf.scenes, _this.gltf.scene || 0);
+                        promises.push(_this.loadSceneAsync("/scenes/" + scene.index, scene));
                     }
                     if (_this._parent.compileMaterials) {
                         promises.push(_this._compileMaterialsAsync());
@@ -3317,7 +3317,7 @@ var BABYLON;
                     for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) {
                         var index = _a[_i];
                         var node = ArrayItem.Get(context + "/nodes/" + index, this.gltf.nodes, index);
-                        promises.push(this.loadNodeAsync("#/nodes/" + node.index, node, function (babylonMesh) {
+                        promises.push(this.loadNodeAsync("/nodes/" + node.index, node, function (babylonMesh) {
                             babylonMesh.parent = _this._rootBabylonMesh;
                         }));
                     }
@@ -3425,17 +3425,18 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (node.name || ""));
                 var loadNode = function (babylonTransformNode) {
+                    GLTFLoader.AddPointerMetadata(babylonTransformNode, context);
                     GLTFLoader._LoadTransform(node, babylonTransformNode);
                     if (node.camera != undefined) {
                         var camera = ArrayItem.Get(context + "/camera", _this.gltf.cameras, node.camera);
-                        promises.push(_this.loadCameraAsync("#/cameras/" + camera.index, camera, function (babylonCamera) {
+                        promises.push(_this.loadCameraAsync("/cameras/" + camera.index, camera, function (babylonCamera) {
                             babylonCamera.parent = babylonTransformNode;
                         }));
                     }
                     if (node.children) {
                         var _loop_1 = function (index) {
                             var childNode = ArrayItem.Get(context + "/children/" + index, _this.gltf.nodes, index);
-                            promises.push(_this.loadNodeAsync("#/nodes/" + node.index, childNode, function (childBabylonMesh) {
+                            promises.push(_this.loadNodeAsync("/nodes/" + childNode.index, childNode, function (childBabylonMesh) {
                                 // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
                                 if (childNode.skin != undefined) {
                                     childBabylonMesh.parent = _this._rootBabylonMesh;
@@ -3458,7 +3459,7 @@ var BABYLON;
                 }
                 else {
                     var mesh = ArrayItem.Get(context + "/mesh", this.gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh.index, node, mesh, loadNode));
+                    promises.push(this._loadMeshAsync("/meshes/" + mesh.index, node, mesh, loadNode));
                 }
                 this.logClose();
                 return Promise.all(promises).then(function () {
@@ -3499,7 +3500,7 @@ var BABYLON;
                 }
                 if (node.skin != undefined) {
                     var skin = ArrayItem.Get(context + "/skin", this.gltf.skins, node.skin);
-                    promises.push(this._loadSkinAsync("#/skins/" + skin.index, node, skin));
+                    promises.push(this._loadSkinAsync("/skins/" + skin.index, node, skin));
                 }
                 assign(node._babylonTransformNode);
                 this.logClose();
@@ -3539,7 +3540,7 @@ var BABYLON;
                     }
                     else {
                         var material = ArrayItem.Get(context + "/material", this.gltf.materials, primitive.material);
-                        promises.push(this._loadMaterialAsync("#/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
+                        promises.push(this._loadMaterialAsync("/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
                             babylonMesh_1.material = babylonMaterial;
                         }));
                     }
@@ -3552,6 +3553,7 @@ var BABYLON;
                     }
                     babylonAbstractMesh = babylonMesh_1;
                 }
+                GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);
                 this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);
                 assign(babylonAbstractMesh);
                 this.logClose();
@@ -3576,7 +3578,7 @@ var BABYLON;
                 }
                 else {
                     var accessor = ArrayItem.Get(context + "/indices", this.gltf.accessors, primitive.indices);
-                    promises.push(this._loadIndicesAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(this._loadIndicesAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         babylonGeometry.setIndices(data);
                     }));
                 }
@@ -3589,7 +3591,7 @@ var BABYLON;
                         babylonMesh._delayInfo.push(kind);
                     }
                     var accessor = ArrayItem.Get(context + "/attributes/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadVertexAccessorAsync("#/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
+                    promises.push(_this._loadVertexAccessorAsync("/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
                         babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
                     }));
                     if (callback) {
@@ -3653,7 +3655,7 @@ var BABYLON;
                         return;
                     }
                     var accessor = ArrayItem.Get(context + "/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(_this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         setData(babylonVertexBuffer, data);
                     }));
                 };
@@ -3766,7 +3768,7 @@ var BABYLON;
                     return Promise.resolve(null);
                 }
                 var accessor = ArrayItem.Get(context + "/inverseBindMatrices", this.gltf.accessors, skin.inverseBindMatrices);
-                return this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor);
+                return this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor);
             };
             GLTFLoader.prototype._updateBoneMatrices = function (babylonSkeleton, inverseBindMatricesData) {
                 for (var _i = 0, _a = babylonSkeleton.bones; _i < _a.length; _i++) {
@@ -3835,8 +3837,9 @@ var BABYLON;
                         throw new Error(context + ": Invalid camera type (" + camera.type + ")");
                     }
                 }
-                assign(babylonCamera);
+                GLTFLoader.AddPointerMetadata(babylonCamera, context);
                 this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
+                assign(babylonCamera);
                 return Promise.all(promises).then(function () {
                     return babylonCamera;
                 });
@@ -3849,7 +3852,7 @@ var BABYLON;
                 var promises = new Array();
                 for (var index = 0; index < animations.length; index++) {
                     var animation = animations[index];
-                    promises.push(this.loadAnimationAsync("#/animations/" + animation.index, animation));
+                    promises.push(this.loadAnimationAsync("/animations/" + animation.index, animation));
                 }
                 return Promise.all(promises).then(function () { });
             };
@@ -4052,8 +4055,8 @@ var BABYLON;
                 var inputAccessor = ArrayItem.Get(context + "/input", this.gltf.accessors, sampler.input);
                 var outputAccessor = ArrayItem.Get(context + "/output", this.gltf.accessors, sampler.output);
                 sampler._data = Promise.all([
-                    this._loadFloatAccessorAsync("#/accessors/" + inputAccessor.index, inputAccessor),
-                    this._loadFloatAccessorAsync("#/accessors/" + outputAccessor.index, outputAccessor)
+                    this._loadFloatAccessorAsync("/accessors/" + inputAccessor.index, inputAccessor),
+                    this._loadFloatAccessorAsync("/accessors/" + outputAccessor.index, outputAccessor)
                 ]).then(function (_a) {
                     var inputData = _a[0], outputData = _a[1];
                     return {
@@ -4085,7 +4088,7 @@ var BABYLON;
                     return bufferView._data;
                 }
                 var buffer = ArrayItem.Get(context + "/buffer", this.gltf.buffers, bufferView.buffer);
-                bufferView._data = this._loadBufferAsync("#/buffers/" + buffer.index, buffer).then(function (data) {
+                bufferView._data = this._loadBufferAsync("/buffers/" + buffer.index, buffer).then(function (data) {
                     try {
                         return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                     }
@@ -4108,7 +4111,7 @@ var BABYLON;
                     return accessor._data;
                 }
                 var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
                 });
                 return accessor._data;
@@ -4129,7 +4132,7 @@ var BABYLON;
                 }
                 else {
                     var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                    accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                    accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                         return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
                     });
                 }
@@ -4139,8 +4142,8 @@ var BABYLON;
                         var indicesBufferView = ArrayItem.Get(context + "/sparse/indices/bufferView", _this.gltf.bufferViews, sparse_1.indices.bufferView);
                         var valuesBufferView = ArrayItem.Get(context + "/sparse/values/bufferView", _this.gltf.bufferViews, sparse_1.values.bufferView);
                         return Promise.all([
-                            _this.loadBufferViewAsync("#/bufferViews/" + indicesBufferView.index, indicesBufferView),
-                            _this.loadBufferViewAsync("#/bufferViews/" + valuesBufferView.index, valuesBufferView)
+                            _this.loadBufferViewAsync("/bufferViews/" + indicesBufferView.index, indicesBufferView),
+                            _this.loadBufferViewAsync("/bufferViews/" + valuesBufferView.index, valuesBufferView)
                         ]).then(function (_a) {
                             var indicesData = _a[0], valuesData = _a[1];
                             var indices = GLTFLoader._GetTypedArray(context + "/sparse/indices", sparse_1.indices.componentType, indicesData, sparse_1.indices.byteOffset, sparse_1.count);
@@ -4163,7 +4166,7 @@ var BABYLON;
                 if (bufferView._babylonBuffer) {
                     return bufferView._babylonBuffer;
                 }
-                bufferView._babylonBuffer = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                bufferView._babylonBuffer = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return new BABYLON.Buffer(_this.babylonScene.getEngine(), data, false);
                 });
                 return bufferView._babylonBuffer;
@@ -4174,14 +4177,14 @@ var BABYLON;
                     return accessor._babylonVertexBuffer;
                 }
                 if (accessor.sparse) {
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
                 // HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
                 else if (accessor.byteOffset && accessor.byteOffset % BABYLON.VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
                     BABYLON.Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
@@ -4211,11 +4214,13 @@ var BABYLON;
                     babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;
                     if (properties.baseColorTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Base Color)";
                             babylonMaterial.albedoTexture = texture;
                         }));
                     }
                     if (properties.metallicRoughnessTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/metallicRoughnessTexture", properties.metallicRoughnessTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Metallic Roughness)";
                             babylonMaterial.metallicTexture = texture;
                         }));
                         babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
@@ -4243,6 +4248,7 @@ var BABYLON;
                         promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial)
                     };
                     material._data[babylonDrawMode] = babylonData;
+                    GLTFLoader.AddPointerMetadata(babylonMaterial, context);
                     this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
                     this.logClose();
                 }
@@ -4283,7 +4289,8 @@ var BABYLON;
                     return extensionPromise;
                 }
                 var name = material.name || "material" + material.index;
-                return this._createDefaultMaterial(name, babylonDrawMode);
+                var babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
+                return babylonMaterial;
             };
             /**
              * Loads properties from a glTF material into a Babylon material.
@@ -4324,6 +4331,7 @@ var BABYLON;
                 }
                 if (material.normalTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/normalTexture", material.normalTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Normal)";
                         babylonMaterial.bumpTexture = texture;
                     }));
                     babylonMaterial.invertNormalMapX = !this.babylonScene.useRightHandedSystem;
@@ -4334,6 +4342,7 @@ var BABYLON;
                 }
                 if (material.occlusionTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/occlusionTexture", material.occlusionTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Occlusion)";
                         babylonMaterial.ambientTexture = texture;
                     }));
                     babylonMaterial.useAmbientInGrayScale = true;
@@ -4343,6 +4352,7 @@ var BABYLON;
                 }
                 if (material.emissiveTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/emissiveTexture", material.emissiveTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Emissive)";
                         babylonMaterial.emissiveTexture = texture;
                     }));
                 }
@@ -4394,6 +4404,7 @@ var BABYLON;
              * @returns A promise that resolves with the loaded Babylon texture when the load is complete
              */
             GLTFLoader.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) {
+                var _this = this;
                 if (assign === void 0) { assign = function () { }; }
                 var extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
                 if (extensionPromise) {
@@ -4401,8 +4412,10 @@ var BABYLON;
                 }
                 this.logOpen("" + context);
                 var texture = ArrayItem.Get(context + "/index", this.gltf.textures, textureInfo.index);
-                var promise = this._loadTextureAsync("#/textures/" + textureInfo.index, texture, function (babylonTexture) {
+                var promise = this._loadTextureAsync("/textures/" + textureInfo.index, texture, function (babylonTexture) {
                     babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
+                    GLTFLoader.AddPointerMetadata(babylonTexture, context);
+                    _this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                     assign(babylonTexture);
                 });
                 this.logClose();
@@ -4414,7 +4427,7 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (texture.name || ""));
                 var sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(context + "/sampler", this.gltf.samplers, texture.sampler));
-                var samplerData = this._loadSampler("#/samplers/" + sampler.index, sampler);
+                var samplerData = this._loadSampler("/samplers/" + sampler.index, sampler);
                 var deferred = new BABYLON.Deferred();
                 var babylonTexture = new BABYLON.Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, function () {
                     if (!_this._disposed) {
@@ -4426,17 +4439,15 @@ var BABYLON;
                     }
                 });
                 promises.push(deferred.promise);
-                babylonTexture.name = texture.name || "texture" + texture.index;
                 babylonTexture.wrapU = samplerData.wrapU;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
-                promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
+                promises.push(this.loadImageAsync("/images/" + image.index, image).then(function (data) {
                     var name = image.uri || _this._fileName + "#image" + image.index;
                     var dataUrl = "data:" + _this._uniqueRootUrl + name;
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);
-                this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                 this.logClose();
                 return Promise.all(promises).then(function () {
                     return babylonTexture;
@@ -4467,7 +4478,7 @@ var BABYLON;
                     }
                     else {
                         var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, image.bufferView);
-                        image._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView);
+                        image._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView);
                     }
                     this.logClose();
                 }
@@ -4547,6 +4558,17 @@ var BABYLON;
                 }
                 this._progressCallback(new BABYLON.SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
+            /**
+             * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+             * @param babylonObject the Babylon object with metadata
+             * @param pointer the JSON pointer
+             */
+            GLTFLoader.AddPointerMetadata = function (babylonObject, pointer) {
+                var metadata = (babylonObject.metadata = babylonObject.metadata || {});
+                var gltf = (metadata.gltf = metadata.gltf || {});
+                var pointers = (gltf.pointers = gltf.pointers || []);
+                pointers.push(pointer);
+            };
             GLTFLoader._GetTextureWrapMode = function (context, mode) {
                 // Set defaults if undefined
                 mode = mode == undefined ? 10497 /* REPEAT */ : mode;
@@ -5575,14 +5597,14 @@ var BABYLON;
                         babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;
                         if (properties.diffuseTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/diffuseTexture", properties.diffuseTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Diffuse)";
                                 babylonMaterial.albedoTexture = texture;
-                                return Promise.resolve();
                             }));
                         }
                         if (properties.specularGlossinessTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/specularGlossinessTexture", properties.specularGlossinessTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Specular Glossiness)";
                                 babylonMaterial.reflectivityTexture = texture;
-                                return Promise.resolve();
                             }));
                             babylonMaterial.reflectivityTexture.hasAlpha = true;
                             babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
@@ -5650,8 +5672,8 @@ var BABYLON;
                             }
                             if (properties.baseColorTexture) {
                                 promises.push(this._loader.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                                    texture.name = babylonMaterial.name + " (Base Color)";
                                     babylonMaterial.albedoTexture = texture;
-                                    return Promise.resolve();
                                 }));
                             }
                         }
@@ -5747,6 +5769,7 @@ var BABYLON;
                                 babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;
                                 babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;
                                 babylonLight.parent = babylonMesh;
+                                GLTF2.GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);
                                 assign(babylonMesh);
                             });
                         });

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 8 - 0
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -1450,6 +1450,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 58 - 35
dist/preview release/loaders/babylonjs.loaders.js

@@ -4211,11 +4211,11 @@ var BABYLON;
                     _this._extensionsOnLoading();
                     var promises = new Array();
                     if (nodes) {
-                        promises.push(_this.loadSceneAsync("#/nodes", { nodes: nodes, index: -1 }));
+                        promises.push(_this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
                     }
                     else {
-                        var scene = ArrayItem.Get("#/scene", _this.gltf.scenes, _this.gltf.scene || 0);
-                        promises.push(_this.loadSceneAsync("#/scenes/" + scene.index, scene));
+                        var scene = ArrayItem.Get("/scene", _this.gltf.scenes, _this.gltf.scene || 0);
+                        promises.push(_this.loadSceneAsync("/scenes/" + scene.index, scene));
                     }
                     if (_this._parent.compileMaterials) {
                         promises.push(_this._compileMaterialsAsync());
@@ -4379,7 +4379,7 @@ var BABYLON;
                     for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) {
                         var index = _a[_i];
                         var node = ArrayItem.Get(context + "/nodes/" + index, this.gltf.nodes, index);
-                        promises.push(this.loadNodeAsync("#/nodes/" + node.index, node, function (babylonMesh) {
+                        promises.push(this.loadNodeAsync("/nodes/" + node.index, node, function (babylonMesh) {
                             babylonMesh.parent = _this._rootBabylonMesh;
                         }));
                     }
@@ -4487,17 +4487,18 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (node.name || ""));
                 var loadNode = function (babylonTransformNode) {
+                    GLTFLoader.AddPointerMetadata(babylonTransformNode, context);
                     GLTFLoader._LoadTransform(node, babylonTransformNode);
                     if (node.camera != undefined) {
                         var camera = ArrayItem.Get(context + "/camera", _this.gltf.cameras, node.camera);
-                        promises.push(_this.loadCameraAsync("#/cameras/" + camera.index, camera, function (babylonCamera) {
+                        promises.push(_this.loadCameraAsync("/cameras/" + camera.index, camera, function (babylonCamera) {
                             babylonCamera.parent = babylonTransformNode;
                         }));
                     }
                     if (node.children) {
                         var _loop_1 = function (index) {
                             var childNode = ArrayItem.Get(context + "/children/" + index, _this.gltf.nodes, index);
-                            promises.push(_this.loadNodeAsync("#/nodes/" + node.index, childNode, function (childBabylonMesh) {
+                            promises.push(_this.loadNodeAsync("/nodes/" + childNode.index, childNode, function (childBabylonMesh) {
                                 // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
                                 if (childNode.skin != undefined) {
                                     childBabylonMesh.parent = _this._rootBabylonMesh;
@@ -4520,7 +4521,7 @@ var BABYLON;
                 }
                 else {
                     var mesh = ArrayItem.Get(context + "/mesh", this.gltf.meshes, node.mesh);
-                    promises.push(this._loadMeshAsync("#/meshes/" + mesh.index, node, mesh, loadNode));
+                    promises.push(this._loadMeshAsync("/meshes/" + mesh.index, node, mesh, loadNode));
                 }
                 this.logClose();
                 return Promise.all(promises).then(function () {
@@ -4561,7 +4562,7 @@ var BABYLON;
                 }
                 if (node.skin != undefined) {
                     var skin = ArrayItem.Get(context + "/skin", this.gltf.skins, node.skin);
-                    promises.push(this._loadSkinAsync("#/skins/" + skin.index, node, skin));
+                    promises.push(this._loadSkinAsync("/skins/" + skin.index, node, skin));
                 }
                 assign(node._babylonTransformNode);
                 this.logClose();
@@ -4601,7 +4602,7 @@ var BABYLON;
                     }
                     else {
                         var material = ArrayItem.Get(context + "/material", this.gltf.materials, primitive.material);
-                        promises.push(this._loadMaterialAsync("#/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
+                        promises.push(this._loadMaterialAsync("/materials/" + material.index, material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) {
                             babylonMesh_1.material = babylonMaterial;
                         }));
                     }
@@ -4614,6 +4615,7 @@ var BABYLON;
                     }
                     babylonAbstractMesh = babylonMesh_1;
                 }
+                GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);
                 this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);
                 assign(babylonAbstractMesh);
                 this.logClose();
@@ -4638,7 +4640,7 @@ var BABYLON;
                 }
                 else {
                     var accessor = ArrayItem.Get(context + "/indices", this.gltf.accessors, primitive.indices);
-                    promises.push(this._loadIndicesAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(this._loadIndicesAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         babylonGeometry.setIndices(data);
                     }));
                 }
@@ -4651,7 +4653,7 @@ var BABYLON;
                         babylonMesh._delayInfo.push(kind);
                     }
                     var accessor = ArrayItem.Get(context + "/attributes/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadVertexAccessorAsync("#/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
+                    promises.push(_this._loadVertexAccessorAsync("/accessors/" + accessor.index, accessor, kind).then(function (babylonVertexBuffer) {
                         babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
                     }));
                     if (callback) {
@@ -4715,7 +4717,7 @@ var BABYLON;
                         return;
                     }
                     var accessor = ArrayItem.Get(context + "/" + attribute, _this.gltf.accessors, attributes[attribute]);
-                    promises.push(_this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    promises.push(_this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         setData(babylonVertexBuffer, data);
                     }));
                 };
@@ -4828,7 +4830,7 @@ var BABYLON;
                     return Promise.resolve(null);
                 }
                 var accessor = ArrayItem.Get(context + "/inverseBindMatrices", this.gltf.accessors, skin.inverseBindMatrices);
-                return this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor);
+                return this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor);
             };
             GLTFLoader.prototype._updateBoneMatrices = function (babylonSkeleton, inverseBindMatricesData) {
                 for (var _i = 0, _a = babylonSkeleton.bones; _i < _a.length; _i++) {
@@ -4897,8 +4899,9 @@ var BABYLON;
                         throw new Error(context + ": Invalid camera type (" + camera.type + ")");
                     }
                 }
-                assign(babylonCamera);
+                GLTFLoader.AddPointerMetadata(babylonCamera, context);
                 this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
+                assign(babylonCamera);
                 return Promise.all(promises).then(function () {
                     return babylonCamera;
                 });
@@ -4911,7 +4914,7 @@ var BABYLON;
                 var promises = new Array();
                 for (var index = 0; index < animations.length; index++) {
                     var animation = animations[index];
-                    promises.push(this.loadAnimationAsync("#/animations/" + animation.index, animation));
+                    promises.push(this.loadAnimationAsync("/animations/" + animation.index, animation));
                 }
                 return Promise.all(promises).then(function () { });
             };
@@ -5114,8 +5117,8 @@ var BABYLON;
                 var inputAccessor = ArrayItem.Get(context + "/input", this.gltf.accessors, sampler.input);
                 var outputAccessor = ArrayItem.Get(context + "/output", this.gltf.accessors, sampler.output);
                 sampler._data = Promise.all([
-                    this._loadFloatAccessorAsync("#/accessors/" + inputAccessor.index, inputAccessor),
-                    this._loadFloatAccessorAsync("#/accessors/" + outputAccessor.index, outputAccessor)
+                    this._loadFloatAccessorAsync("/accessors/" + inputAccessor.index, inputAccessor),
+                    this._loadFloatAccessorAsync("/accessors/" + outputAccessor.index, outputAccessor)
                 ]).then(function (_a) {
                     var inputData = _a[0], outputData = _a[1];
                     return {
@@ -5147,7 +5150,7 @@ var BABYLON;
                     return bufferView._data;
                 }
                 var buffer = ArrayItem.Get(context + "/buffer", this.gltf.buffers, bufferView.buffer);
-                bufferView._data = this._loadBufferAsync("#/buffers/" + buffer.index, buffer).then(function (data) {
+                bufferView._data = this._loadBufferAsync("/buffers/" + buffer.index, buffer).then(function (data) {
                     try {
                         return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                     }
@@ -5170,7 +5173,7 @@ var BABYLON;
                     return accessor._data;
                 }
                 var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
                 });
                 return accessor._data;
@@ -5191,7 +5194,7 @@ var BABYLON;
                 }
                 else {
                     var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, accessor.bufferView);
-                    accessor._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                    accessor._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                         return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
                     });
                 }
@@ -5201,8 +5204,8 @@ var BABYLON;
                         var indicesBufferView = ArrayItem.Get(context + "/sparse/indices/bufferView", _this.gltf.bufferViews, sparse_1.indices.bufferView);
                         var valuesBufferView = ArrayItem.Get(context + "/sparse/values/bufferView", _this.gltf.bufferViews, sparse_1.values.bufferView);
                         return Promise.all([
-                            _this.loadBufferViewAsync("#/bufferViews/" + indicesBufferView.index, indicesBufferView),
-                            _this.loadBufferViewAsync("#/bufferViews/" + valuesBufferView.index, valuesBufferView)
+                            _this.loadBufferViewAsync("/bufferViews/" + indicesBufferView.index, indicesBufferView),
+                            _this.loadBufferViewAsync("/bufferViews/" + valuesBufferView.index, valuesBufferView)
                         ]).then(function (_a) {
                             var indicesData = _a[0], valuesData = _a[1];
                             var indices = GLTFLoader._GetTypedArray(context + "/sparse/indices", sparse_1.indices.componentType, indicesData, sparse_1.indices.byteOffset, sparse_1.count);
@@ -5225,7 +5228,7 @@ var BABYLON;
                 if (bufferView._babylonBuffer) {
                     return bufferView._babylonBuffer;
                 }
-                bufferView._babylonBuffer = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
+                bufferView._babylonBuffer = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView).then(function (data) {
                     return new BABYLON.Buffer(_this.babylonScene.getEngine(), data, false);
                 });
                 return bufferView._babylonBuffer;
@@ -5236,14 +5239,14 @@ var BABYLON;
                     return accessor._babylonVertexBuffer;
                 }
                 if (accessor.sparse) {
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
                 // HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
                 else if (accessor.byteOffset && accessor.byteOffset % BABYLON.VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
                     BABYLON.Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
-                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("#/accessors/" + accessor.index, accessor).then(function (data) {
+                    accessor._babylonVertexBuffer = this._loadFloatAccessorAsync("/accessors/" + accessor.index, accessor).then(function (data) {
                         return new BABYLON.VertexBuffer(_this.babylonScene.getEngine(), data, kind, false);
                     });
                 }
@@ -5273,11 +5276,13 @@ var BABYLON;
                     babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor;
                     if (properties.baseColorTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Base Color)";
                             babylonMaterial.albedoTexture = texture;
                         }));
                     }
                     if (properties.metallicRoughnessTexture) {
                         promises.push(this.loadTextureInfoAsync(context + "/metallicRoughnessTexture", properties.metallicRoughnessTexture, function (texture) {
+                            texture.name = babylonMaterial.name + " (Metallic Roughness)";
                             babylonMaterial.metallicTexture = texture;
                         }));
                         babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
@@ -5305,6 +5310,7 @@ var BABYLON;
                         promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial)
                     };
                     material._data[babylonDrawMode] = babylonData;
+                    GLTFLoader.AddPointerMetadata(babylonMaterial, context);
                     this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
                     this.logClose();
                 }
@@ -5345,7 +5351,8 @@ var BABYLON;
                     return extensionPromise;
                 }
                 var name = material.name || "material" + material.index;
-                return this._createDefaultMaterial(name, babylonDrawMode);
+                var babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
+                return babylonMaterial;
             };
             /**
              * Loads properties from a glTF material into a Babylon material.
@@ -5386,6 +5393,7 @@ var BABYLON;
                 }
                 if (material.normalTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/normalTexture", material.normalTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Normal)";
                         babylonMaterial.bumpTexture = texture;
                     }));
                     babylonMaterial.invertNormalMapX = !this.babylonScene.useRightHandedSystem;
@@ -5396,6 +5404,7 @@ var BABYLON;
                 }
                 if (material.occlusionTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/occlusionTexture", material.occlusionTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Occlusion)";
                         babylonMaterial.ambientTexture = texture;
                     }));
                     babylonMaterial.useAmbientInGrayScale = true;
@@ -5405,6 +5414,7 @@ var BABYLON;
                 }
                 if (material.emissiveTexture) {
                     promises.push(this.loadTextureInfoAsync(context + "/emissiveTexture", material.emissiveTexture, function (texture) {
+                        texture.name = babylonMaterial.name + " (Emissive)";
                         babylonMaterial.emissiveTexture = texture;
                     }));
                 }
@@ -5456,6 +5466,7 @@ var BABYLON;
              * @returns A promise that resolves with the loaded Babylon texture when the load is complete
              */
             GLTFLoader.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) {
+                var _this = this;
                 if (assign === void 0) { assign = function () { }; }
                 var extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign);
                 if (extensionPromise) {
@@ -5463,8 +5474,10 @@ var BABYLON;
                 }
                 this.logOpen("" + context);
                 var texture = ArrayItem.Get(context + "/index", this.gltf.textures, textureInfo.index);
-                var promise = this._loadTextureAsync("#/textures/" + textureInfo.index, texture, function (babylonTexture) {
+                var promise = this._loadTextureAsync("/textures/" + textureInfo.index, texture, function (babylonTexture) {
                     babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
+                    GLTFLoader.AddPointerMetadata(babylonTexture, context);
+                    _this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                     assign(babylonTexture);
                 });
                 this.logClose();
@@ -5476,7 +5489,7 @@ var BABYLON;
                 var promises = new Array();
                 this.logOpen(context + " " + (texture.name || ""));
                 var sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(context + "/sampler", this.gltf.samplers, texture.sampler));
-                var samplerData = this._loadSampler("#/samplers/" + sampler.index, sampler);
+                var samplerData = this._loadSampler("/samplers/" + sampler.index, sampler);
                 var deferred = new BABYLON.Deferred();
                 var babylonTexture = new BABYLON.Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, function () {
                     if (!_this._disposed) {
@@ -5488,17 +5501,15 @@ var BABYLON;
                     }
                 });
                 promises.push(deferred.promise);
-                babylonTexture.name = texture.name || "texture" + texture.index;
                 babylonTexture.wrapU = samplerData.wrapU;
                 babylonTexture.wrapV = samplerData.wrapV;
                 var image = ArrayItem.Get(context + "/source", this.gltf.images, texture.source);
-                promises.push(this.loadImageAsync("#/images/" + image.index, image).then(function (data) {
+                promises.push(this.loadImageAsync("/images/" + image.index, image).then(function (data) {
                     var name = image.uri || _this._fileName + "#image" + image.index;
                     var dataUrl = "data:" + _this._uniqueRootUrl + name;
                     babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
                 }));
                 assign(babylonTexture);
-                this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                 this.logClose();
                 return Promise.all(promises).then(function () {
                     return babylonTexture;
@@ -5529,7 +5540,7 @@ var BABYLON;
                     }
                     else {
                         var bufferView = ArrayItem.Get(context + "/bufferView", this.gltf.bufferViews, image.bufferView);
-                        image._data = this.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView);
+                        image._data = this.loadBufferViewAsync("/bufferViews/" + bufferView.index, bufferView);
                     }
                     this.logClose();
                 }
@@ -5609,6 +5620,17 @@ var BABYLON;
                 }
                 this._progressCallback(new BABYLON.SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             };
+            /**
+             * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+             * @param babylonObject the Babylon object with metadata
+             * @param pointer the JSON pointer
+             */
+            GLTFLoader.AddPointerMetadata = function (babylonObject, pointer) {
+                var metadata = (babylonObject.metadata = babylonObject.metadata || {});
+                var gltf = (metadata.gltf = metadata.gltf || {});
+                var pointers = (gltf.pointers = gltf.pointers || []);
+                pointers.push(pointer);
+            };
             GLTFLoader._GetTextureWrapMode = function (context, mode) {
                 // Set defaults if undefined
                 mode = mode == undefined ? 10497 /* REPEAT */ : mode;
@@ -6637,14 +6659,14 @@ var BABYLON;
                         babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor;
                         if (properties.diffuseTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/diffuseTexture", properties.diffuseTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Diffuse)";
                                 babylonMaterial.albedoTexture = texture;
-                                return Promise.resolve();
                             }));
                         }
                         if (properties.specularGlossinessTexture) {
                             promises.push(this._loader.loadTextureInfoAsync(context + "/specularGlossinessTexture", properties.specularGlossinessTexture, function (texture) {
+                                texture.name = babylonMaterial.name + " (Specular Glossiness)";
                                 babylonMaterial.reflectivityTexture = texture;
-                                return Promise.resolve();
                             }));
                             babylonMaterial.reflectivityTexture.hasAlpha = true;
                             babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
@@ -6712,8 +6734,8 @@ var BABYLON;
                             }
                             if (properties.baseColorTexture) {
                                 promises.push(this._loader.loadTextureInfoAsync(context + "/baseColorTexture", properties.baseColorTexture, function (texture) {
+                                    texture.name = babylonMaterial.name + " (Base Color)";
                                     babylonMaterial.albedoTexture = texture;
-                                    return Promise.resolve();
                                 }));
                             }
                         }
@@ -6809,6 +6831,7 @@ var BABYLON;
                                 babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity;
                                 babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;
                                 babylonLight.parent = babylonMesh;
+                                GLTF2.GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);
                                 assign(babylonMesh);
                             });
                         });

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


+ 8 - 0
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -1457,6 +1457,14 @@ declare module BABYLON.GLTF2 {
          */
         loadUriAsync(context: string, uri: string): Promise<ArrayBufferView>;
         private _onProgress;
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        static AddPointerMetadata(babylonObject: {
+            metadata: any;
+        }, pointer: string): void;
         private static _GetTextureWrapMode;
         private static _GetTextureSamplingMode;
         private static _GetTypedArray;

+ 5 - 19
dist/preview release/viewer/babylon.viewer.d.ts

@@ -117,11 +117,11 @@ declare module BabylonViewer {
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
-            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
+            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
             /**
                 * Hide the overlay screen.
                 */
-            hideOverlayScreen(): Promise<Template> | Promise<string>;
+            hideOverlayScreen(): Promise<string> | Promise<Template>;
             /**
                 * show the viewer (in case it was hidden)
                 *
@@ -138,11 +138,11 @@ declare module BabylonViewer {
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 */
-            showLoadingScreen(): Promise<Template> | Promise<string>;
+            showLoadingScreen(): Promise<string> | Promise<Template>;
             /**
                 * Hide the loading screen
                 */
-            hideLoadingScreen(): Promise<Template> | Promise<string>;
+            hideLoadingScreen(): Promise<string> | Promise<Template>;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
@@ -873,7 +873,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1507,20 +1507,6 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-declare module BabylonViewer {
 }
 declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 1
dist/preview release/viewer/babylon.viewer.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -148,11 +148,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
-            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
+            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
             /**
                 * Hide the overlay screen.
                 */
-            hideOverlayScreen(): Promise<Template> | Promise<string>;
+            hideOverlayScreen(): Promise<string> | Promise<Template>;
             /**
                 * show the viewer (in case it was hidden)
                 *
@@ -169,11 +169,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 */
-            showLoadingScreen(): Promise<Template> | Promise<string>;
+            showLoadingScreen(): Promise<string> | Promise<Template>;
             /**
                 * Hide the loading screen
                 */
-            hideLoadingScreen(): Promise<Template> | Promise<string>;
+            hideLoadingScreen(): Promise<string> | Promise<Template>;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
@@ -933,14 +933,13 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
-    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1611,22 +1610,6 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
-declare module 'babylonjs-viewer/optimizer/custom/extended' {
-    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
-    /**
-        * A custom upgrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedUpgrade(sceneManager: SceneManager): boolean;
-    /**
-        * A custom degrade-oriented function configuration for the scene optimizer.
-        *
-        * @param viewer the viewer to optimize
-        */
-    export function extendedDegrade(sceneManager: SceneManager): boolean;
-}
-
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';

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

@@ -29,7 +29,7 @@
 - Added support for performing operations like select all, text highlight, delete selected in `inputText` ([Saket Saurabh](https://github.com/ssaket))
 - Added `inputText.onTextCopyObservable`, `inputText.onTextCutObservable` and `inputText.onTextPasteObservable` to inputText ([Saket Saurabh](https://github.com/ssaket))
 - Added `AdvancedDynamicTexture.onClipboardObservable` to observe for clipboard events in AdvancedDynamicTexture([Saket Saurabh](https://github.com/ssaket))
-
+- Added `inputText.onFocusSelectAll` to allow complete selection of text on focus event.([Saket Saurabh](https://github.com/ssaket))
 
 ### Core Engine
 
@@ -59,11 +59,13 @@
 - Add updateUpVectorFromRotation to target camera to allow the up vector to be computed from rotation ([TrevorDev](https://github.com/TrevorDev))
 - Added opacity texture support to `GridMaterial` ([Deltakosh](https://github.com/deltakosh))
 - Added support for deserializing morph target animations in animation groups
+- AssetContainer dispose method ([TrevorDev](https://github.com/TrevorDev))
 
 ### glTF Loader
 
 - Added support for mesh instancing for improved performance when multiple nodes point to the same mesh ([bghgary](https://github.com/bghgary))
 - Create `TransformNode` objects instead of `Mesh` objects for glTF nodes without geometry ([bghgary](https://github.com/bghgary))
+- Added glTF JSON pointers to metadata of nodes, materials, and textures ([bghgary](https://github.com/bghgary))
 
 ### glTF Serializer
 

+ 35 - 14
gui/src/2D/controls/inputText.ts

@@ -34,6 +34,7 @@ export class InputText extends Control implements IFocusableControl {
     private _highlightedText = "";
     private _startHighlightIndex = 0;
     private _endHighlightIndex = 0;
+    private _onFocusSelectAll = false;
     private _onClipboardObserver: Nullable<Observer<ClipboardInfo>>;
     private _onPointerDblTapObserver: Nullable<Observer<PointerInfo>>;
 
@@ -80,7 +81,7 @@ export class InputText extends Control implements IFocusableControl {
         }
     }
 
-    /** Gets and sets the text highlighter transparency; default: 0.4 */
+    /** Gets or sets the text highlighter transparency; default: 0.4 */
     public get highligherOpacity(): number {
         return this._highligherOpacity;
     }
@@ -92,8 +93,21 @@ export class InputText extends Control implements IFocusableControl {
         this._highligherOpacity = value;
         this._markAsDirty();
     }
+    /** Gets or sets a boolean indicating whether to select complete text by default on input focus */
+    public get onFocusSelectAll(): boolean {
+        return this._onFocusSelectAll;
+    }
+
+    public set onFocusSelectAll(value: boolean) {
+        if (this._onFocusSelectAll === value) {
+            return;
+        }
+
+        this._onFocusSelectAll = value;
+        this._markAsDirty();
+    }
 
-    /** Gets and sets the text hightlight color */
+    /** Gets or sets the text hightlight color */
     public get textHighlightColor(): string {
         return this._textHighlightColor;
     }
@@ -368,6 +382,10 @@ export class InputText extends Control implements IFocusableControl {
             });
         }
 
+        if (this._onFocusSelectAll) {
+            this._selectAllText();
+        }
+
     }
 
     protected _getTypeName(): string {
@@ -395,19 +413,8 @@ export class InputText extends Control implements IFocusableControl {
 
         //select all
         if (evt && (evt.ctrlKey || evt.metaKey) && keyCode === 65) {
-
-            this._blinkIsEven = false;
-            this._isTextHighlightOn = true;
+            this._selectAllText();
             evt.preventDefault();
-
-            //if already highlighted pass
-            if (this._highlightedText) {
-                return;
-            }
-
-            this._startHighlightIndex = 0;
-            this._endHighlightIndex = this._text.length;
-            this._cursorOffset = 0;
             return;
         }
         // Specific cases
@@ -560,6 +567,20 @@ export class InputText extends Control implements IFocusableControl {
         this._isTextHighlightOn = true;
         this._blinkIsEven = false;
     }
+    /** @hidden */
+    private _selectAllText() {
+        this._blinkIsEven = false;
+        this._isTextHighlightOn = true;
+
+        //if already highlighted pass
+        if (this._highlightedText) {
+            return;
+        }
+
+        this._startHighlightIndex = 0;
+        this._endHighlightIndex = this._text.length;
+        this._cursorOffset = 0;
+    }
 
     /**
      * Handles the keyboard event

+ 5 - 8
inspector/src/Inspector.ts

@@ -24,9 +24,6 @@ export interface IInspectorOptions {
     embedHostRoot?: HTMLElement;
     showExplorer?: boolean;
     showInspector?: boolean;
-    explorerWidth?: string;
-    inspectorWidth?: string;
-    embedHostWidth?: string;
     embedMode?: boolean;
     handleResize?: boolean;
     enablePopup?: boolean;
@@ -36,6 +33,9 @@ export interface IInspectorOptions {
 interface IInternalInspectorOptions extends IInspectorOptions {
     popup: boolean;
     original: boolean;
+    explorerWidth?: string;
+    inspectorWidth?: string;
+    embedHostWidth?: string;
 }
 
 export class Inspector {
@@ -99,7 +99,7 @@ export class Inspector {
                 this._SceneExplorerHost = parentControlExplorer.ownerDocument!.createElement("div");
 
                 this._SceneExplorerHost.id = "scene-explorer-host";
-                this._SceneExplorerHost.style.width = options.explorerWidth || "auto";
+                this._SceneExplorerHost.style.width = options.explorerWidth || "300px";
 
                 parentControlExplorer.appendChild(this._SceneExplorerHost);
 
@@ -161,7 +161,7 @@ export class Inspector {
                 const host = parentControlActions.ownerDocument!.createElement("div");
 
                 host.id = "inspector-host";
-                host.style.width = options.inspectorWidth || "auto";
+                host.style.width = options.inspectorWidth || "300px";
 
                 parentControlActions.appendChild(host);
 
@@ -331,9 +331,6 @@ export class Inspector {
             embedMode: false,
             handleResize: true,
             enablePopup: true,
-            inspectorWidth: "auto",
-            explorerWidth: "auto",
-            embedHostWidth: "auto",
             ...userOptions
         };
 

+ 18 - 11
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx

@@ -36,17 +36,9 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                 <TextureLinkLineComponent label="Refraction" texture={material.refractionTexture} material={material} onSelectionChangeObservable={this.props.onSelectionChangeObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
                 <TextureLinkLineComponent label="Micro-surface" texture={material.microSurfaceTexture} material={material} onSelectionChangeObservable={this.props.onSelectionChangeObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
                 <TextureLinkLineComponent label="Bump" texture={material.bumpTexture} material={material} onSelectionChangeObservable={this.props.onSelectionChangeObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
-                {
-                    material.bumpTexture &&
-                    <SliderLineComponent label="Bump strength" target={material.bumpTexture} propertyName="level" minimum={0} maximum={2} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                }
                 <TextureLinkLineComponent label="Emissive" texture={material.emissiveTexture} material={material} onSelectionChangeObservable={this.props.onSelectionChangeObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
                 <TextureLinkLineComponent label="Opacity" texture={material.opacityTexture} material={material} onSelectionChangeObservable={this.props.onSelectionChangeObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
                 <TextureLinkLineComponent label="Ambient" texture={material.ambientTexture} material={material} onSelectionChangeObservable={this.props.onSelectionChangeObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
-                {
-                    material.ambientTexture &&
-                    <SliderLineComponent label="Ambient strength" target={material} propertyName="ambientTextureStrength" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                }
                 <TextureLinkLineComponent label="Lightmap" texture={material.lightmapTexture} material={material} onSelectionChangeObservable={this.props.onSelectionChangeObservable} onDebugSelectionChangeObservable={onDebugSelectionChangeObservable} />
             </LineContainerComponent>
         )
@@ -64,8 +56,26 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                     <Color3LineComponent label="Emissive" target={material} propertyName="emissiveColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <Color3LineComponent label="Ambient" target={material} propertyName="ambientColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent label="Alpha" target={material} propertyName="alpha" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    {
+                        material.bumpTexture &&
+                        <SliderLineComponent label="Bump strength" target={material.bumpTexture} propertyName="level" minimum={0} maximum={2} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    }
+                    {
+                        material.ambientTexture &&
+                        <SliderLineComponent label="Ambient strength" target={material} propertyName="ambientTextureStrength" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    }
+                    {
+                        material.reflectionTexture &&
+                        <SliderLineComponent label="Reflection strength" target={material.reflectionTexture} propertyName="level" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    }
                 </LineContainerComponent>
                 {this.renderTextures()}
+                <LineContainerComponent title="LEVELS" closed={true}>
+                    <SliderLineComponent label="Environment intensity" target={material} propertyName="environmentIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Metallic" target={material} propertyName="metallic" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Micro-surface" target={material} propertyName="microSurface" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Specular intensity" target={material} propertyName="specularIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
                 <LineContainerComponent title="RENDERING" closed={true}>
                     <CheckBoxLineComponent label="Alpha from albedo" target={material} propertyName="useAlphaFromAlbedoTexture" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Ambient in grayscale" target={material} propertyName="useAmbientInGrayScale" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
@@ -76,9 +86,6 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                     <CheckBoxLineComponent label="Specular anti-aliasing" target={material} propertyName="enableSpecularAntiAliasing" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
                 <LineContainerComponent title="ADVANCED" closed={true}>
-                    <SliderLineComponent label="Metallic" target={material} propertyName="metallic" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    <SliderLineComponent label="Micro-surface" target={material} propertyName="microSurface" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    <SliderLineComponent label="Specular intensity" target={material} propertyName="specularIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Radiance occlusion" target={material} propertyName="useRadianceOcclusion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Horizon occlusion " target={material} propertyName="useHorizonOcclusion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Unlit" target={material} propertyName="unlit" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 2 - 0
loaders/src/glTF/2.0/Extensions/KHR_lights_punctual.ts

@@ -97,6 +97,8 @@ module BABYLON.GLTF2.Loader.Extensions {
                     babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range;
                     babylonLight.parent = babylonMesh;
 
+                    GLTFLoader.AddPointerMetadata(babylonLight, extensionContext);
+
                     assign(babylonMesh);
                 });
             });

+ 2 - 2
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -67,15 +67,15 @@ module BABYLON.GLTF2.Loader.Extensions {
 
             if (properties.diffuseTexture) {
                 promises.push(this._loader.loadTextureInfoAsync(`${context}/diffuseTexture`, properties.diffuseTexture, (texture) => {
+                    texture.name = `${babylonMaterial.name} (Diffuse)`;
                     babylonMaterial.albedoTexture = texture;
-                    return Promise.resolve();
                 }));
             }
 
             if (properties.specularGlossinessTexture) {
                 promises.push(this._loader.loadTextureInfoAsync(`${context}/specularGlossinessTexture`, properties.specularGlossinessTexture, (texture) => {
+                    texture.name = `${babylonMaterial.name} (Specular Glossiness)`;
                     babylonMaterial.reflectivityTexture = texture;
-                    return Promise.resolve();
                 }));
 
                 babylonMaterial.reflectivityTexture.hasAlpha = true;

+ 1 - 1
loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts

@@ -53,8 +53,8 @@ module BABYLON.GLTF2.Loader.Extensions {
 
                 if (properties.baseColorTexture) {
                     promises.push(this._loader.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => {
+                        texture.name = `${babylonMaterial.name} (Base Color)`;
                         babylonMaterial.albedoTexture = texture;
-                        return Promise.resolve();
                     }));
                 }
             }

+ 56 - 32
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -231,11 +231,11 @@ module BABYLON.GLTF2 {
                 const promises = new Array<Promise<any>>();
 
                 if (nodes) {
-                    promises.push(this.loadSceneAsync("#/nodes", { nodes: nodes, index: -1 }));
+                    promises.push(this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 }));
                 }
                 else {
-                    const scene = ArrayItem.Get(`#/scene`, this.gltf.scenes, this.gltf.scene || 0);
-                    promises.push(this.loadSceneAsync(`#/scenes/${scene.index}`, scene));
+                    const scene = ArrayItem.Get(`/scene`, this.gltf.scenes, this.gltf.scene || 0);
+                    promises.push(this.loadSceneAsync(`/scenes/${scene.index}`, scene));
                 }
 
                 if (this._parent.compileMaterials) {
@@ -426,7 +426,7 @@ module BABYLON.GLTF2 {
             if (scene.nodes) {
                 for (let index of scene.nodes) {
                     const node = ArrayItem.Get(`${context}/nodes/${index}`, this.gltf.nodes, index);
-                    promises.push(this.loadNodeAsync(`#/nodes/${node.index}`, node, (babylonMesh) => {
+                    promises.push(this.loadNodeAsync(`/nodes/${node.index}`, node, (babylonMesh) => {
                         babylonMesh.parent = this._rootBabylonMesh;
                     }));
                 }
@@ -547,11 +547,12 @@ module BABYLON.GLTF2 {
             this.logOpen(`${context} ${node.name || ""}`);
 
             const loadNode = (babylonTransformNode: TransformNode) => {
+                GLTFLoader.AddPointerMetadata(babylonTransformNode, context);
                 GLTFLoader._LoadTransform(node, babylonTransformNode);
 
                 if (node.camera != undefined) {
                     const camera = ArrayItem.Get(`${context}/camera`, this.gltf.cameras, node.camera);
-                    promises.push(this.loadCameraAsync(`#/cameras/${camera.index}`, camera, (babylonCamera) => {
+                    promises.push(this.loadCameraAsync(`/cameras/${camera.index}`, camera, (babylonCamera) => {
                         babylonCamera.parent = babylonTransformNode;
                     }));
                 }
@@ -559,7 +560,7 @@ module BABYLON.GLTF2 {
                 if (node.children) {
                     for (const index of node.children) {
                         const childNode = ArrayItem.Get(`${context}/children/${index}`, this.gltf.nodes, index);
-                        promises.push(this.loadNodeAsync(`#/nodes/${node.index}`, childNode, (childBabylonMesh) => {
+                        promises.push(this.loadNodeAsync(`/nodes/${childNode.index}`, childNode, (childBabylonMesh) => {
                             // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note)
                             if (childNode.skin != undefined) {
                                 childBabylonMesh.parent = this._rootBabylonMesh;
@@ -581,7 +582,7 @@ module BABYLON.GLTF2 {
             }
             else {
                 const mesh = ArrayItem.Get(`${context}/mesh`, this.gltf.meshes, node.mesh);
-                promises.push(this._loadMeshAsync(`#/meshes/${mesh.index}`, node, mesh, loadNode));
+                promises.push(this._loadMeshAsync(`/meshes/${mesh.index}`, node, mesh, loadNode));
             }
 
             this.logClose();
@@ -631,7 +632,7 @@ module BABYLON.GLTF2 {
 
             if (node.skin != undefined) {
                 const skin = ArrayItem.Get(`${context}/skin`, this.gltf.skins, node.skin);
-                promises.push(this._loadSkinAsync(`#/skins/${skin.index}`, node, skin));
+                promises.push(this._loadSkinAsync(`/skins/${skin.index}`, node, skin));
             }
 
             assign(node._babylonTransformNode!);
@@ -680,7 +681,7 @@ module BABYLON.GLTF2 {
                 }
                 else {
                     const material = ArrayItem.Get(`${context}/material`, this.gltf.materials, primitive.material);
-                    promises.push(this._loadMaterialAsync(`#/materials/${material.index}`, material, babylonMesh, babylonDrawMode, (babylonMaterial) => {
+                    promises.push(this._loadMaterialAsync(`/materials/${material.index}`, material, babylonMesh, babylonDrawMode, (babylonMaterial) => {
                         babylonMesh.material = babylonMaterial;
                     }));
                 }
@@ -697,6 +698,7 @@ module BABYLON.GLTF2 {
                 babylonAbstractMesh = babylonMesh;
             }
 
+            GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context);
             this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh);
             assign(babylonAbstractMesh);
 
@@ -727,7 +729,7 @@ module BABYLON.GLTF2 {
             }
             else {
                 const accessor = ArrayItem.Get(`${context}/indices`, this.gltf.accessors, primitive.indices);
-                promises.push(this._loadIndicesAccessorAsync(`#/accessors/${accessor.index}`, accessor).then((data) => {
+                promises.push(this._loadIndicesAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
                     babylonGeometry.setIndices(data);
                 }));
             }
@@ -743,7 +745,7 @@ module BABYLON.GLTF2 {
                 }
 
                 const accessor = ArrayItem.Get(`${context}/attributes/${attribute}`, this.gltf.accessors, attributes[attribute]);
-                promises.push(this._loadVertexAccessorAsync(`#/accessors/${accessor.index}`, accessor, kind).then((babylonVertexBuffer) => {
+                promises.push(this._loadVertexAccessorAsync(`/accessors/${accessor.index}`, accessor, kind).then((babylonVertexBuffer) => {
                     babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count);
                 }));
 
@@ -820,7 +822,7 @@ module BABYLON.GLTF2 {
                 }
 
                 const accessor = ArrayItem.Get(`${context}/${attribute}`, this.gltf.accessors, attributes[attribute]);
-                promises.push(this._loadFloatAccessorAsync(`#/accessors/${accessor.index}`, accessor).then((data) => {
+                promises.push(this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
                     setData(babylonVertexBuffer, data);
                 }));
             };
@@ -950,7 +952,7 @@ module BABYLON.GLTF2 {
             }
 
             const accessor = ArrayItem.Get(`${context}/inverseBindMatrices`, this.gltf.accessors, skin.inverseBindMatrices);
-            return this._loadFloatAccessorAsync(`#/accessors/${accessor.index}`, accessor);
+            return this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor);
         }
 
         private _updateBoneMatrices(babylonSkeleton: Skeleton, inverseBindMatricesData: Nullable<Float32Array>): void {
@@ -1032,8 +1034,9 @@ module BABYLON.GLTF2 {
                 }
             }
 
-            assign(babylonCamera);
+            GLTFLoader.AddPointerMetadata(babylonCamera, context);
             this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
+            assign(babylonCamera);
 
             return Promise.all(promises).then(() => {
                 return babylonCamera;
@@ -1050,7 +1053,7 @@ module BABYLON.GLTF2 {
 
             for (let index = 0; index < animations.length; index++) {
                 const animation = animations[index];
-                promises.push(this.loadAnimationAsync(`#/animations/${animation.index}`, animation));
+                promises.push(this.loadAnimationAsync(`/animations/${animation.index}`, animation));
             }
 
             return Promise.all(promises).then(() => { });
@@ -1268,8 +1271,8 @@ module BABYLON.GLTF2 {
             const inputAccessor = ArrayItem.Get(`${context}/input`, this.gltf.accessors, sampler.input);
             const outputAccessor = ArrayItem.Get(`${context}/output`, this.gltf.accessors, sampler.output);
             sampler._data = Promise.all([
-                this._loadFloatAccessorAsync(`#/accessors/${inputAccessor.index}`, inputAccessor),
-                this._loadFloatAccessorAsync(`#/accessors/${outputAccessor.index}`, outputAccessor)
+                this._loadFloatAccessorAsync(`/accessors/${inputAccessor.index}`, inputAccessor),
+                this._loadFloatAccessorAsync(`/accessors/${outputAccessor.index}`, outputAccessor)
             ]).then(([inputData, outputData]) => {
                 return {
                     input: inputData,
@@ -1307,7 +1310,7 @@ module BABYLON.GLTF2 {
             }
 
             const buffer = ArrayItem.Get(`${context}/buffer`, this.gltf.buffers, bufferView.buffer);
-            bufferView._data = this._loadBufferAsync(`#/buffers/${buffer.index}`, buffer).then((data) => {
+            bufferView._data = this._loadBufferAsync(`/buffers/${buffer.index}`, buffer).then((data) => {
                 try {
                     return new Uint8Array(data.buffer, data.byteOffset + (bufferView.byteOffset || 0), bufferView.byteLength);
                 }
@@ -1335,7 +1338,7 @@ module BABYLON.GLTF2 {
             }
 
             const bufferView = ArrayItem.Get(`${context}/bufferView`, this.gltf.bufferViews, accessor.bufferView);
-            accessor._data = this.loadBufferViewAsync(`#/bufferViews/${bufferView.index}`, bufferView).then((data) => {
+            accessor._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {
                 return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count);
             });
 
@@ -1361,7 +1364,7 @@ module BABYLON.GLTF2 {
             }
             else {
                 const bufferView = ArrayItem.Get(`${context}/bufferView`, this.gltf.bufferViews, accessor.bufferView);
-                accessor._data = this.loadBufferViewAsync(`#/bufferViews/${bufferView.index}`, bufferView).then((data) => {
+                accessor._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {
                     return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length);
                 });
             }
@@ -1372,8 +1375,8 @@ module BABYLON.GLTF2 {
                     const indicesBufferView = ArrayItem.Get(`${context}/sparse/indices/bufferView`, this.gltf.bufferViews, sparse.indices.bufferView);
                     const valuesBufferView = ArrayItem.Get(`${context}/sparse/values/bufferView`, this.gltf.bufferViews, sparse.values.bufferView);
                     return Promise.all([
-                        this.loadBufferViewAsync(`#/bufferViews/${indicesBufferView.index}`, indicesBufferView),
-                        this.loadBufferViewAsync(`#/bufferViews/${valuesBufferView.index}`, valuesBufferView)
+                        this.loadBufferViewAsync(`/bufferViews/${indicesBufferView.index}`, indicesBufferView),
+                        this.loadBufferViewAsync(`/bufferViews/${valuesBufferView.index}`, valuesBufferView)
                     ]).then(([indicesData, valuesData]) => {
                         const indices = GLTFLoader._GetTypedArray(`${context}/sparse/indices`, sparse.indices.componentType, indicesData, sparse.indices.byteOffset, sparse.count) as IndicesArray;
                         const values = GLTFLoader._GetTypedArray(`${context}/sparse/values`, accessor.componentType, valuesData, sparse.values.byteOffset, numComponents * sparse.count) as Float32Array;
@@ -1399,7 +1402,7 @@ module BABYLON.GLTF2 {
                 return bufferView._babylonBuffer;
             }
 
-            bufferView._babylonBuffer = this.loadBufferViewAsync(`#/bufferViews/${bufferView.index}`, bufferView).then((data) => {
+            bufferView._babylonBuffer = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView).then((data) => {
                 return new Buffer(this.babylonScene.getEngine(), data, false);
             });
 
@@ -1412,14 +1415,14 @@ module BABYLON.GLTF2 {
             }
 
             if (accessor.sparse) {
-                accessor._babylonVertexBuffer = this._loadFloatAccessorAsync(`#/accessors/${accessor.index}`, accessor).then((data) => {
+                accessor._babylonVertexBuffer = this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
                     return new VertexBuffer(this.babylonScene.getEngine(), data, kind, false);
                 });
             }
             // HACK: If byte offset is not a multiple of component type byte length then load as a float array instead of using Babylon buffers.
             else if (accessor.byteOffset && accessor.byteOffset % VertexBuffer.GetTypeByteLength(accessor.componentType) !== 0) {
                 Tools.Warn("Accessor byte offset is not a multiple of component type byte length");
-                accessor._babylonVertexBuffer = this._loadFloatAccessorAsync(`#/accessors/${accessor.index}`, accessor).then((data) => {
+                accessor._babylonVertexBuffer = this._loadFloatAccessorAsync(`/accessors/${accessor.index}`, accessor).then((data) => {
                     return new VertexBuffer(this.babylonScene.getEngine(), data, kind, false);
                 });
             }
@@ -1456,12 +1459,14 @@ module BABYLON.GLTF2 {
 
                 if (properties.baseColorTexture) {
                     promises.push(this.loadTextureInfoAsync(`${context}/baseColorTexture`, properties.baseColorTexture, (texture) => {
+                        texture.name = `${babylonMaterial.name} (Base Color)`;
                         babylonMaterial.albedoTexture = texture;
                     }));
                 }
 
                 if (properties.metallicRoughnessTexture) {
                     promises.push(this.loadTextureInfoAsync(`${context}/metallicRoughnessTexture`, properties.metallicRoughnessTexture, (texture) => {
+                        texture.name = `${babylonMaterial.name} (Metallic Roughness)`;
                         babylonMaterial.metallicTexture = texture;
                     }));
 
@@ -1496,6 +1501,7 @@ module BABYLON.GLTF2 {
 
                 material._data[babylonDrawMode] = babylonData;
 
+                GLTFLoader.AddPointerMetadata(babylonMaterial, context);
                 this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 
                 this.logClose();
@@ -1544,7 +1550,9 @@ module BABYLON.GLTF2 {
             }
 
             const name = material.name || `material${material.index}`;
-            return this._createDefaultMaterial(name, babylonDrawMode);
+            const babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
+
+            return babylonMaterial;
         }
 
         /**
@@ -1595,6 +1603,7 @@ module BABYLON.GLTF2 {
 
             if (material.normalTexture) {
                 promises.push(this.loadTextureInfoAsync(`${context}/normalTexture`, material.normalTexture, (texture) => {
+                    texture.name = `${babylonMaterial.name} (Normal)`;
                     babylonMaterial.bumpTexture = texture;
                 }));
 
@@ -1607,6 +1616,7 @@ module BABYLON.GLTF2 {
 
             if (material.occlusionTexture) {
                 promises.push(this.loadTextureInfoAsync(`${context}/occlusionTexture`, material.occlusionTexture, (texture) => {
+                    texture.name = `${babylonMaterial.name} (Occlusion)`;
                     babylonMaterial.ambientTexture = texture;
                 }));
 
@@ -1618,6 +1628,7 @@ module BABYLON.GLTF2 {
 
             if (material.emissiveTexture) {
                 promises.push(this.loadTextureInfoAsync(`${context}/emissiveTexture`, material.emissiveTexture, (texture) => {
+                    texture.name = `${babylonMaterial.name} (Emissive)`;
                     babylonMaterial.emissiveTexture = texture;
                 }));
             }
@@ -1681,8 +1692,11 @@ module BABYLON.GLTF2 {
             this.logOpen(`${context}`);
 
             const texture = ArrayItem.Get(`${context}/index`, this.gltf.textures, textureInfo.index);
-            const promise = this._loadTextureAsync(`#/textures/${textureInfo.index}`, texture, (babylonTexture) => {
+            const promise = this._loadTextureAsync(`/textures/${textureInfo.index}`, texture, (babylonTexture) => {
                 babylonTexture.coordinatesIndex = textureInfo.texCoord || 0;
+
+                GLTFLoader.AddPointerMetadata(babylonTexture, context);
+                this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
                 assign(babylonTexture);
             });
 
@@ -1697,7 +1711,7 @@ module BABYLON.GLTF2 {
             this.logOpen(`${context} ${texture.name || ""}`);
 
             const sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(`${context}/sampler`, this.gltf.samplers, texture.sampler));
-            const samplerData = this._loadSampler(`#/samplers/${sampler.index}`, sampler);
+            const samplerData = this._loadSampler(`/samplers/${sampler.index}`, sampler);
 
             const deferred = new Deferred<void>();
             const babylonTexture = new Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, () => {
@@ -1711,19 +1725,17 @@ module BABYLON.GLTF2 {
             });
             promises.push(deferred.promise);
 
-            babylonTexture.name = texture.name || `texture${texture.index}`;
             babylonTexture.wrapU = samplerData.wrapU;
             babylonTexture.wrapV = samplerData.wrapV;
 
             const image = ArrayItem.Get(`${context}/source`, this.gltf.images, texture.source);
-            promises.push(this.loadImageAsync(`#/images/${image.index}`, image).then((data) => {
+            promises.push(this.loadImageAsync(`/images/${image.index}`, image).then((data) => {
                 const name = image.uri || `${this._fileName}#image${image.index}`;
                 const dataUrl = `data:${this._uniqueRootUrl}${name}`;
                 babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
             }));
 
             assign(babylonTexture);
-            this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
 
             this.logClose();
 
@@ -1760,7 +1772,7 @@ module BABYLON.GLTF2 {
                 }
                 else {
                     const bufferView = ArrayItem.Get(`${context}/bufferView`, this.gltf.bufferViews, image.bufferView);
-                    image._data = this.loadBufferViewAsync(`#/bufferViews/${bufferView.index}`, bufferView);
+                    image._data = this.loadBufferViewAsync(`/bufferViews/${bufferView.index}`, bufferView);
                 }
 
                 this.logClose();
@@ -1852,6 +1864,18 @@ module BABYLON.GLTF2 {
             this._progressCallback(new SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
         }
 
+        /**
+         * Adds a JSON pointer to the metadata of the Babylon object at `<object>.metadata.gltf.pointers`.
+         * @param babylonObject the Babylon object with metadata
+         * @param pointer the JSON pointer
+         */
+        public static AddPointerMetadata(babylonObject: { metadata: any }, pointer: string): void {
+            const metadata = (babylonObject.metadata = babylonObject.metadata || {});
+            const gltf = (metadata.gltf = metadata.gltf || {});
+            const pointers = (gltf.pointers = gltf.pointers || []);
+            pointers.push(pointer);
+        }
+
         private static _GetTextureWrapMode(context: string, mode: TextureWrapMode | undefined): number {
             // Set defaults if undefined
             mode = mode == undefined ? TextureWrapMode.REPEAT : mode;

+ 6 - 0
src/Materials/Textures/babylon.baseTexture.ts

@@ -23,6 +23,12 @@ module BABYLON {
         @serialize()
         public name: string;
 
+        /**
+         * Gets or sets an object used to store user defined information.
+         */
+        @serialize()
+        public metadata: any = null;
+
         @serialize("hasAlpha")
         private _hasAlpha = false;
         /**

+ 43 - 0
src/babylon.assetContainer.ts

@@ -125,6 +125,49 @@ module BABYLON {
             }
         }
 
+        /**
+         * Disposes all the assets in the container
+         */
+        public dispose() {
+            this.cameras.forEach((o) => {
+                o.dispose();
+            });
+            this.lights.forEach((o) => {
+                o.dispose();
+            });
+            this.meshes.forEach((o) => {
+                o.dispose();
+            });
+            this.skeletons.forEach((o) => {
+                o.dispose();
+            });
+            this.animationGroups.forEach((o) => {
+                o.dispose();
+            });
+            this.multiMaterials.forEach((o) => {
+                o.dispose();
+            });
+            this.materials.forEach((o) => {
+                o.dispose();
+            });
+            this.geometries.forEach((o) => {
+                o.dispose();
+            });
+            this.transformNodes.forEach((o) => {
+                o.dispose();
+            });
+            this.actionManagers.forEach((o) => {
+                o.dispose();
+            });
+            this.textures.forEach((o) => {
+                o.dispose();
+            });
+
+            for (let component of this.scene._serializableComponents) {
+                component.dispose();
+            }
+        }
+
         private _moveAssets<T>(sourceAssets: T[], targetAssets: T[], keepAssets: T[]): void {
             if (!sourceAssets) {
                 return;

+ 4 - 13
tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

@@ -88,7 +88,7 @@ describe('Babylon Scene Loader', function() {
             let parsedCount = 0;
             let meshCount = 0;
             let materialCount = 0;
-            let textureCounts: { [name: string]: number } = {};
+            let textureCount = 0;
             let ready = false;
 
             const promises = new Array<Promise<void>>();
@@ -105,8 +105,7 @@ describe('Babylon Scene Loader', function() {
                     materialCount++;
                 };
                 loader.onTextureLoaded = texture => {
-                    textureCounts[texture.name] = textureCounts[texture.name] || 0;
-                    textureCounts[texture.name]++;
+                    textureCount++;
                 };
 
                 promises.push(loader.whenCompleteAsync().then(() => {
@@ -122,16 +121,8 @@ describe('Babylon Scene Loader', function() {
                 expect(meshCount, "meshCount").to.equal(scene.meshes.length);
                 expect(materialCount, "materialCount").to.equal(scene.materials.length);
 
-                const expectedTextureLoadCounts = {
-                    "baseColor": 1,
-                    "occlusionRoughnessMetallic": 2,
-                    "normal": 1,
-                    "emissive": 1
-                };
-                expect(Object.keys(textureCounts), "Object.keys(textureCounts)").to.have.lengthOf(Object.keys(expectedTextureLoadCounts).length);
-                for (const textureName in expectedTextureLoadCounts) {
-                    expect(textureCounts, "textureCounts").to.have.property(textureName, expectedTextureLoadCounts[textureName]);
-                }
+                const filteredTextures = scene.textures.filter((texture) => texture !== scene._environmentBRDFTexture);
+                expect(textureCount, "textureCount").to.equal(filteredTextures.length);
             }));
 
             return Promise.all(promises);