Jelajahi Sumber

Merge pull request #4468 from bghgary/gltf-logging

Add initial logging to glTF loader
David Catuhe 7 tahun lalu
induk
melakukan
aaeb3441c8

+ 2 - 2
Tools/Gulp/config.json

@@ -14,7 +14,7 @@
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
             "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
-            "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
         ],
         ],
         "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
         "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
         "srcOutputDirectory": "../../src/",
         "srcOutputDirectory": "../../src/",
@@ -1894,7 +1894,7 @@
                             "addBabylonDeclaration": [
                             "addBabylonDeclaration": [
                                 "babylon.d.ts",
                                 "babylon.d.ts",
                                 "loaders/babylonjs.loaders.d.ts",
                                 "loaders/babylonjs.loaders.d.ts",
-                                "gltf2Interface/babylon.glTF2Interface.d.ts"
+                                "glTF2Interface/babylon.glTF2Interface.d.ts"
                             ]
                             ]
                         }
                         }
                     ],
                     ],

+ 1 - 1
Tools/Gulp/gulpfile.js

@@ -906,7 +906,7 @@ gulp.task("typedoc-generate", function () {
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
             "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
-            "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"])
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"])
         .pipe(typedoc({
         .pipe(typedoc({
             // TypeScript options (see typescript docs)
             // TypeScript options (see typescript docs)
             mode: "modules",
             mode: "modules",

dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts → dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts


dist/preview release/gltf2Interface/package.json → dist/preview release/glTF2Interface/package.json


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

@@ -39,6 +39,7 @@
 - Added support for KHR_texture_transform ([bghgary](http://www.github.com/bghgary))
 - Added support for KHR_texture_transform ([bghgary](http://www.github.com/bghgary))
 - Added `onNodeLODsLoadedObservable` and `onMaterialLODsLoadedObservable` to MSFT_lod loader extension ([bghgary](http://www.github.com/bghgary))
 - Added `onNodeLODsLoadedObservable` and `onMaterialLODsLoadedObservable` to MSFT_lod loader extension ([bghgary](http://www.github.com/bghgary))
 - Added glTF loader settings to the GLTF tab in the debug layer ([bghgary](http://www.github.com/bghgary))
 - Added glTF loader settings to the GLTF tab in the debug layer ([bghgary](http://www.github.com/bghgary))
+- Added support for debug logging ([bghgary](http://www.github.com/bghgary))
 
 
 ### Viewer
 ### Viewer
 
 

+ 1 - 1
inspector/src/details/Property.ts

@@ -12,7 +12,7 @@ module INSPECTOR {
         /** The obj parent  */
         /** The obj parent  */
         private _parentObj: any;
         private _parentObj: any;
 
 
-        constructor(prop: string, obj: any, parentObj?: PropertyLine) {
+        constructor(prop: string, obj: any, parentObj?: any) {
             this._property = prop;
             this._property = prop;
             this._obj = obj;
             this._obj = obj;
             this._parentObj = parentObj || null;
             this._parentObj = parentObj || null;

+ 107 - 59
inspector/src/tabs/GLTFTab.ts

@@ -1,18 +1,23 @@
-/// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 /// <reference path="../../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts"/>
 /// <reference path="../../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts"/>
 
 
 declare function Split(elements: HTMLElement[], options: any): any;
 declare function Split(elements: HTMLElement[], options: any): any;
 
 
 module INSPECTOR {
 module INSPECTOR {
-    interface ILoaderExtensionSettings {
+    interface ILoaderDefaults {
         [extensionName: string]: {
         [extensionName: string]: {
-            [settingName: string]: any
+            [key: string]: any
+        },
+        extensions: {
+            [extensionName: string]: {
+                [key: string]: any
+            }
         }
         }
-    };
+    }
 
 
     export class GLTFTab extends Tab {
     export class GLTFTab extends Tab {
-        private static _LoaderExtensionSettings: ILoaderExtensionSettings | null = null;
+        private static _LoaderDefaults: ILoaderDefaults | null = null;
 
 
         private _inspector: Inspector;
         private _inspector: Inspector;
         private _actions: HTMLDivElement;
         private _actions: HTMLDivElement;
@@ -25,14 +30,20 @@ module INSPECTOR {
 
 
         /** @hidden */
         /** @hidden */
         public static _Initialize(): void {
         public static _Initialize(): void {
-            // Must register with OnPluginActivatedObservable as early as possible to
-            // override the default settings for each extension.
+            // Must register with OnPluginActivatedObservable as early as possible to override the loader defaults.
             BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
             BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
-                if (loader.name === "gltf" && GLTFTab._LoaderExtensionSettings) {
+                if (loader.name === "gltf" && GLTFTab._LoaderDefaults) {
+                    const defaults = GLTFTab._LoaderDefaults;
+                    for (const key in defaults) {
+                        if (key !== "extensions") {
+                            (loader as any)[key] = GLTFTab._LoaderDefaults[key];
+                        }
+                    }
+
                     loader.onExtensionLoadedObservable.add(extension => {
                     loader.onExtensionLoadedObservable.add(extension => {
-                        const settings = GLTFTab._LoaderExtensionSettings![extension.name];
-                        for (const settingName in settings) {
-                            (extension as any)[settingName] = settings[settingName];
+                        const extensionDefaults = defaults.extensions[extension.name];
+                        for (const key in extensionDefaults) {
+                            (extension as any)[key] = extensionDefaults[key];
                         }
                         }
                     });
                     });
                 }
                 }
@@ -65,36 +76,44 @@ module INSPECTOR {
         }
         }
 
 
         private _addImport() {
         private _addImport() {
-            const importActions = Helpers.CreateDiv(null, this._actions) as HTMLDivElement;
+            const importTitle = Helpers.CreateDiv('gltf-title', this._actions);
+            importTitle.textContent = 'Import';
+
+            const importActions = Helpers.CreateDiv('gltf-actions', this._actions) as HTMLDivElement;
 
 
-            this._getLoaderExtensionOverridesAsync().then(loaderExtensionSettings => {
-                const title = Helpers.CreateDiv('gltf-title', importActions);
-                title.textContent = 'Import';
+            this._getLoaderDefaultsAsync().then(defaults => {
+                importTitle.addEventListener('click', event => {
+                    this._showLoaderDefaults(defaults);
+                    event.stopPropagation();
+                });
 
 
-                const extensionActions = Helpers.CreateDiv('gltf-actions', importActions) as HTMLDivElement;
+                importActions.addEventListener('click', event => {
+                    this._showLoaderDefaults(defaults);
+                    event.stopPropagation();
+                });
 
 
-                const extensionsTitle = Helpers.CreateDiv('gltf-title', extensionActions) as HTMLDivElement;
+                const extensionsTitle = Helpers.CreateDiv('gltf-title', importActions) as HTMLDivElement;
                 extensionsTitle.textContent = "Extensions";
                 extensionsTitle.textContent = "Extensions";
 
 
-                for (const extensionName in loaderExtensionSettings) {
-                    const settings = loaderExtensionSettings[extensionName];
+                for (const extensionName in defaults.extensions) {
+                    const extensionDefaults = defaults.extensions[extensionName];
 
 
-                    const extensionAction = Helpers.CreateDiv('gltf-action', extensionActions);
+                    const extensionAction = Helpers.CreateDiv('gltf-action', importActions);
                     extensionAction.addEventListener('click', event => {
                     extensionAction.addEventListener('click', event => {
-                        if (this._updateLoaderExtensionDetails(settings)) {
+                        if (this._showLoaderExtensionDefaults(extensionDefaults)) {
                             event.stopPropagation();
                             event.stopPropagation();
                         }
                         }
                     });
                     });
 
 
                     const checkbox = Helpers.CreateElement('span', 'gltf-checkbox', extensionAction);
                     const checkbox = Helpers.CreateElement('span', 'gltf-checkbox', extensionAction);
 
 
-                    if (settings.enabled) {
+                    if (extensionDefaults.enabled) {
                         checkbox.classList.add('action', 'active');
                         checkbox.classList.add('action', 'active');
                     }
                     }
 
 
                     checkbox.addEventListener('click', () => {
                     checkbox.addEventListener('click', () => {
                         checkbox.classList.toggle('active');
                         checkbox.classList.toggle('active');
-                        settings.enabled = checkbox.classList.contains('active');
+                        extensionDefaults.enabled = checkbox.classList.contains('active');
                     });
                     });
 
 
                     const label = Helpers.CreateElement('span', null, extensionAction);
                     const label = Helpers.CreateElement('span', null, extensionAction);
@@ -103,43 +122,53 @@ module INSPECTOR {
             });
             });
         }
         }
 
 
-        private _getLoaderExtensionOverridesAsync(): Promise<ILoaderExtensionSettings> {
-            if (GLTFTab._LoaderExtensionSettings) {
-                return Promise.resolve(GLTFTab._LoaderExtensionSettings);
+        private static _EnumeratePublic(obj: any, callback: (key: string, value: any) => void): void {
+            for (const key in obj) {
+                if (key !== "name" && key[0] !== '_') {
+                    const value = obj[key];
+                    const type = typeof value;
+                    if (type !== "object" && type !== "function" && type !== "undefined") {
+                        callback(key, value);
+                    }
+                }
             }
             }
+        }
 
 
-            const loaderExtensionSettings: ILoaderExtensionSettings = {};
+        private _getLoaderDefaultsAsync(): Promise<ILoaderDefaults> {
+            if (GLTFTab._LoaderDefaults) {
+                return Promise.resolve(GLTFTab._LoaderDefaults);
+            }
+
+            const defaults: ILoaderDefaults = {
+                extensions: {}
+            };
 
 
             const engine = new BABYLON.NullEngine();
             const engine = new BABYLON.NullEngine();
             const scene = new BABYLON.Scene(engine);
             const scene = new BABYLON.Scene(engine);
-            const loader = new BABYLON.GLTF2.GLTFLoader();
+
+            const loader = new BABYLON.GLTFFileLoader();
+            GLTFTab._EnumeratePublic(loader, (key, value) => {
+                defaults[key] = value;
+            });
+
             loader.onExtensionLoadedObservable.add(extension => {
             loader.onExtensionLoadedObservable.add(extension => {
-                loaderExtensionSettings[extension.name] = {};
-                const settings = loaderExtensionSettings[extension.name];
-                for (const key of Object.keys(extension)) {
-                    if (key !== "name" && key[0] !== '_') {
-                        const value = (extension as any)[key];
-                        if (typeof value !== "object") {
-                            settings[key] = value;
-                        }
-                    }
-                }
+                const extensionDefaults: any = {};
+                GLTFTab._EnumeratePublic(extension, (key, value) => {
+                    extensionDefaults[key] = value;
+                });
+                defaults.extensions[extension.name] = extensionDefaults;
             });
             });
 
 
-            const data = { json: {}, bin: null };
-            return loader.importMeshAsync([], scene, data, "").then(() => {
+            const data = '{ "asset": { "version": "2.0" }, "scenes": [ { } ] }';
+            return loader.loadAsync(scene, data, "").then(() => {
                 scene.dispose();
                 scene.dispose();
                 engine.dispose();
                 engine.dispose();
 
 
-                return (GLTFTab._LoaderExtensionSettings = loaderExtensionSettings);
+                return (GLTFTab._LoaderDefaults = defaults);
             });
             });
         }
         }
 
 
-        private _updateLoaderExtensionDetails(settings: { [settingName: string]: any }): boolean {
-            if (Object.keys(settings).length === 1) {
-                return false;
-            }
-
+        private _openDetailsPanel(): DetailPanel {
             if (!this._detailsPanel) {
             if (!this._detailsPanel) {
                 this._detailsPanel = new DetailPanel();
                 this._detailsPanel = new DetailPanel();
                 this._panel.appendChild(this._detailsPanel.toHtml());
                 this._panel.appendChild(this._detailsPanel.toHtml());
@@ -152,16 +181,7 @@ module INSPECTOR {
             }
             }
 
 
             this._detailsPanel.clean();
             this._detailsPanel.clean();
-
-            const details = new Array<PropertyLine>();
-            for (const key in settings) {
-                if (key !== "enabled") {
-                    details.push(new PropertyLine(new Property(key, settings)));
-                }
-            }
-            this._detailsPanel.details = details;
-
-            return true;
+            return this._detailsPanel;
         }
         }
 
 
         private _closeDetailsPanel(): void {
         private _closeDetailsPanel(): void {
@@ -177,11 +197,39 @@ module INSPECTOR {
             }
             }
         }
         }
 
 
+        private _showLoaderDefaults(defaults: { [key: string]: any }): void {
+            var detailsPanel = this._openDetailsPanel();
+            const details = new Array<PropertyLine>();
+            for (const key in defaults) {
+                if (key !== "extensions") {
+                    details.push(new PropertyLine(new Property(key, defaults, this._inspector.scene)));
+                }
+            }
+            detailsPanel.details = details;
+        }
+
+        private _showLoaderExtensionDefaults(defaults: { [key: string]: any }): boolean {
+            if (Object.keys(defaults).length === 1) {
+                return false;
+            }
+
+            var detailsPanel = this._openDetailsPanel();
+            const details = new Array<PropertyLine>();
+            for (const key in defaults) {
+                if (key !== "enabled") {
+                    details.push(new PropertyLine(new Property(key, defaults, this._inspector.scene)));
+                }
+            }
+            detailsPanel.details = details;
+
+            return true;
+        }
+
         private _addExport() {
         private _addExport() {
-            const exportActions = Helpers.CreateDiv(null, this._actions) as HTMLDivElement;
+            const exportTitle = Helpers.CreateDiv('gltf-title', this._actions);
+            exportTitle.textContent = 'Export';
 
 
-            const title = Helpers.CreateDiv('gltf-title', exportActions);
-            title.textContent = 'Export';
+            const exportActions = Helpers.CreateDiv('gltf-actions', this._actions) as HTMLDivElement;
 
 
             const name = Helpers.CreateInput('gltf-input', exportActions);
             const name = Helpers.CreateInput('gltf-input', exportActions);
             name.placeholder = "File name...";
             name.placeholder = "File name...";

+ 3 - 20
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1562,28 +1562,11 @@ module BABYLON.GLTF1 {
             GLTFLoader.Extensions[extension.name] = extension;
             GLTFLoader.Extensions[extension.name] = extension;
         }
         }
 
 
-        // #region Stubs for IGLTFLoader interface
-        public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
-        public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
-        public compileMaterials = false;
-        public useClipPlane = false;
-        public compileShadowGenerators = false;
-        public transparencyAsCoverage = false;
-        public _normalizeAnimationGroupsToBeginAtZero = true;
-        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
-
-        public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
-        public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
-        public readonly onMaterialLoadedObservable = new Observable<Material>();
-        public readonly onCameraLoadedObservable = new Observable<Camera>();
-        public readonly onCompleteObservable = new Observable<IGLTFLoader>();
-        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
-        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
-
         public state: Nullable<GLTFLoaderState> = null;
         public state: Nullable<GLTFLoaderState> = null;
 
 
-        public dispose(): void {}
-        // #endregion
+        public dispose(): void {
+            // do nothing
+        }
 
 
         private _importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], skeletons: Skeleton[]) => void, onProgress?: (event: SceneLoaderProgressEvent) => void, onError?: (message: string) => void): boolean {
         private _importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], skeletons: Skeleton[]) => void, onProgress?: (event: SceneLoaderProgressEvent) => void, onError?: (message: string) => void): boolean {
             scene.useRightHandedSystem = true;
             scene.useRightHandedSystem = true;

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

@@ -30,7 +30,7 @@ module BABYLON.GLTF2.Extensions {
                     promises.push(this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
                     promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
 
 
-                    this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                    this._loader._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 
 
                     babylonData = {
                     babylonData = {
                         material: babylonMaterial,
                         material: babylonMaterial,

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

@@ -20,7 +20,7 @@ module BABYLON.GLTF2.Extensions {
 
 
                     const promise = this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
                     const promise = this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
 
 
-                    this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                    this._loader._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 
 
                     babylonData = {
                     babylonData = {
                         material: babylonMaterial,
                         material: babylonMaterial,

+ 14 - 0
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -46,12 +46,14 @@ module BABYLON.GLTF2.Extensions {
             this._loader._onReadyObservable.addOnce(() => {
             this._loader._onReadyObservable.addOnce(() => {
                 for (let indexLOD = 0; indexLOD < this._loadNodePromises.length; indexLOD++) {
                 for (let indexLOD = 0; indexLOD < this._loadNodePromises.length; indexLOD++) {
                     Promise.all(this._loadNodePromises[indexLOD]).then(() => {
                     Promise.all(this._loadNodePromises[indexLOD]).then(() => {
+                        this._loader._parent._log(`Loaded node LOD ${indexLOD}`);
                         this.onNodeLODsLoadedObservable.notifyObservers(indexLOD);
                         this.onNodeLODsLoadedObservable.notifyObservers(indexLOD);
                     });
                     });
                 }
                 }
 
 
                 for (let indexLOD = 0; indexLOD < this._loadMaterialPromises.length; indexLOD++) {
                 for (let indexLOD = 0; indexLOD < this._loadMaterialPromises.length; indexLOD++) {
                     Promise.all(this._loadMaterialPromises[indexLOD]).then(() => {
                     Promise.all(this._loadMaterialPromises[indexLOD]).then(() => {
+                        this._loader._parent._log(`Loaded material LOD ${indexLOD}`);
                         this.onMaterialLODsLoadedObservable.notifyObservers(indexLOD);
                         this.onMaterialLODsLoadedObservable.notifyObservers(indexLOD);
                     });
                     });
                 }
                 }
@@ -75,6 +77,8 @@ module BABYLON.GLTF2.Extensions {
                 let firstPromise: Promise<void>;
                 let firstPromise: Promise<void>;
 
 
                 const nodeLODs = this._getLODs(extensionContext, node, this._loader._gltf.nodes, extension.ids);
                 const nodeLODs = this._getLODs(extensionContext, node, this._loader._gltf.nodes, extension.ids);
+                this._loader._parent._logOpen(`${extensionContext}`);
+
                 for (let indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) {
                 for (let indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) {
                     const nodeLOD = nodeLODs[indexLOD];
                     const nodeLOD = nodeLODs[indexLOD];
 
 
@@ -117,6 +121,7 @@ module BABYLON.GLTF2.Extensions {
                     this._loadNodePromises[indexLOD].push(promise);
                     this._loadNodePromises[indexLOD].push(promise);
                 }
                 }
 
 
+                this._loader._parent._logClose();
                 return firstPromise!;
                 return firstPromise!;
             });
             });
         }
         }
@@ -131,6 +136,8 @@ module BABYLON.GLTF2.Extensions {
                 let firstPromise: Promise<void>;
                 let firstPromise: Promise<void>;
 
 
                 const materialLODs = this._getLODs(extensionContext, material, this._loader._gltf.materials, extension.ids);
                 const materialLODs = this._getLODs(extensionContext, material, this._loader._gltf.materials, extension.ids);
+                this._loader._parent._logOpen(`${extensionContext}`);
+
                 for (let indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) {
                 for (let indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) {
                     const materialLOD = materialLODs[indexLOD];
                     const materialLOD = materialLODs[indexLOD];
 
 
@@ -175,11 +182,18 @@ module BABYLON.GLTF2.Extensions {
                     this._loadMaterialPromises[indexLOD].push(promise);
                     this._loadMaterialPromises[indexLOD].push(promise);
                 }
                 }
 
 
+                this._loader._parent._logClose();
                 return firstPromise!;
                 return firstPromise!;
             });
             });
         }
         }
 
 
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>> {
         protected _loadUriAsync(context: string, uri: string): Nullable<Promise<ArrayBufferView>> {
+            if (this._loadingMaterialLOD || this._loadingNodeLOD) {
+                if (this._loader._parent.loggingEnabled) {
+                    this._loader._parent._log(`deferred`);
+                }
+            }
+
             // Defer the loading of uris if loading a material or node LOD.
             // Defer the loading of uris if loading a material or node LOD.
             if (this._loadingMaterialLOD) {
             if (this._loadingMaterialLOD) {
                 const index = this._loadingMaterialLOD._index;
                 const index = this._loadingMaterialLOD._index;

+ 126 - 206
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -20,20 +20,12 @@ module BABYLON.GLTF2 {
         }
         }
     }
     }
 
 
-    /**
-     * Loader for loading a glTF 2.0 asset
-     */
+    /** @hidden */
     export class GLTFLoader implements IGLTFLoader {
     export class GLTFLoader implements IGLTFLoader {
-        /** @hidden */
+        public _parent: GLTFFileLoader;
         public _gltf: _ILoaderGLTF;
         public _gltf: _ILoaderGLTF;
-
-        /** @hidden */
         public _babylonScene: Scene;
         public _babylonScene: Scene;
-
-        /** @hidden */
         public _completePromises = new Array<Promise<void>>();
         public _completePromises = new Array<Promise<void>>();
-
-        /** @hidden */
         public _onReadyObservable = new Observable<IGLTFLoader>();
         public _onReadyObservable = new Observable<IGLTFLoader>();
 
 
         private _disposed = false;
         private _disposed = false;
@@ -49,7 +41,6 @@ module BABYLON.GLTF2 {
         private static _ExtensionNames = new Array<string>();
         private static _ExtensionNames = new Array<string>();
         private static _ExtensionFactories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
         private static _ExtensionFactories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
 
 
-        /** @hidden */
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
             if (GLTFLoader._ExtensionFactories[name]) {
             if (GLTFLoader._ExtensionFactories[name]) {
                 Tools.Error(`Extension with the name '${name}' already exists`);
                 Tools.Error(`Extension with the name '${name}' already exists`);
@@ -63,93 +54,16 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         /**
         /**
-         * Mode that determines the coordinate system to use.
-         */
-        public coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO;
-
-        /**
-         * Mode that determines what animations will start.
-         */
-        public animationStartMode = GLTFLoaderAnimationStartMode.FIRST;
-
-        /**
-         * Defines if the loader should compile materials.
-         */
-        public compileMaterials = false;
-
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        public useClipPlane = false;
-
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        public compileShadowGenerators = false;
-
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage. 
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        public transparencyAsCoverage = false;
-
-        /** @hidden */
-        public _normalizeAnimationGroupsToBeginAtZero = true;
-
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
-
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
-
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
-
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        public readonly onMaterialLoadedObservable = new Observable<Material>();
-
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        public readonly onCameraLoadedObservable = new Observable<Camera>();
-
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        public readonly onCompleteObservable = new Observable<IGLTFLoader>();
-
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
-
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
-
-        /**
          * Loader state or null if the loader is not active.
          * Loader state or null if the loader is not active.
          */
          */
         public get state(): Nullable<GLTFLoaderState> {
         public get state(): Nullable<GLTFLoaderState> {
             return this._state;
             return this._state;
         }
         }
 
 
-        /**
-         * Disposes the loader, releases resources during load, and cancels any outstanding requests.
-         */
+        constructor(parent: GLTFFileLoader) {
+            this._parent = parent;
+        }
+
         public dispose(): void {
         public dispose(): void {
             if (this._disposed) {
             if (this._disposed) {
                 return;
                 return;
@@ -157,21 +71,29 @@ module BABYLON.GLTF2 {
 
 
             this._disposed = true;
             this._disposed = true;
 
 
-            this.onDisposeObservable.notifyObservers(this);
-            this.onDisposeObservable.clear();
+            for (const request of this._requests) {
+                request.abort();
+            }
+
+            this._requests.length = 0;
+
+            delete this._gltf;
+            delete this._babylonScene;
+            this._completePromises.length = 0;
+            this._onReadyObservable.clear();
+
+            for (const name in this._extensions) {
+                this._extensions[name].dispose();
+            }
+
+            this._extensions = {};
+
+            delete this._rootBabylonMesh;
+            delete this._progressCallback;
 
 
-            this._clear();
+            this._parent._clear();
         }
         }
 
 
-        /**
-         * Imports one or more meshes from the loaded glTF data and adds them to the scene
-         * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file
-         * @param scene the scene the meshes should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise containg the loaded meshes, particles, skeletons and animations
-         */
         public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
         public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
             return Promise.resolve().then(() => {
             return Promise.resolve().then(() => {
                 this._babylonScene = scene;
                 this._babylonScene = scene;
@@ -213,14 +135,6 @@ module BABYLON.GLTF2 {
             });
             });
         }
         }
 
 
-        /**
-         * Imports all objects from the loaded glTF data and adds them to the scene
-         * @param scene the scene the objects should be added to
-         * @param data the glTF data to load
-         * @param rootUrl root url to load from
-         * @param onProgress event that fires when loading progress has occured
-         * @returns a promise which completes when objects have been loaded to the scene
-         */
         public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
         public loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
             return Promise.resolve().then(() => {
             return Promise.resolve().then(() => {
                 this._babylonScene = scene;
                 this._babylonScene = scene;
@@ -234,6 +148,7 @@ module BABYLON.GLTF2 {
         private _loadAsync(nodes: Nullable<Array<_ILoaderNode>>): Promise<void> {
         private _loadAsync(nodes: Nullable<Array<_ILoaderNode>>): Promise<void> {
             return Promise.resolve().then(() => {
             return Promise.resolve().then(() => {
                 this._state = GLTFLoaderState.LOADING;
                 this._state = GLTFLoaderState.LOADING;
+                this._parent._log(`Loading`);
 
 
                 this._loadExtensions();
                 this._loadExtensions();
                 this._checkExtensions();
                 this._checkExtensions();
@@ -248,16 +163,18 @@ module BABYLON.GLTF2 {
                     promises.push(this._loadSceneAsync(`#/scenes/${scene._index}`, scene));
                     promises.push(this._loadSceneAsync(`#/scenes/${scene._index}`, scene));
                 }
                 }
 
 
-                if (this.compileMaterials) {
+                if (this._parent.compileMaterials) {
                     promises.push(this._compileMaterialsAsync());
                     promises.push(this._compileMaterialsAsync());
                 }
                 }
 
 
-                if (this.compileShadowGenerators) {
+                if (this._parent.compileShadowGenerators) {
                     promises.push(this._compileShadowGeneratorsAsync());
                     promises.push(this._compileShadowGeneratorsAsync());
                 }
                 }
 
 
                 const resultPromise = Promise.all(promises).then(() => {
                 const resultPromise = Promise.all(promises).then(() => {
                     this._state = GLTFLoaderState.READY;
                     this._state = GLTFLoaderState.READY;
+                    this._parent._log(`Ready`);
+
                     this._onReadyObservable.notifyObservers(this);
                     this._onReadyObservable.notifyObservers(this);
                     this._startAnimations();
                     this._startAnimations();
                 });
                 });
@@ -271,12 +188,14 @@ module BABYLON.GLTF2 {
                         if (!this._disposed) {
                         if (!this._disposed) {
                             Promise.all(this._completePromises).then(() => {
                             Promise.all(this._completePromises).then(() => {
                                 this._state = GLTFLoaderState.COMPLETE;
                                 this._state = GLTFLoaderState.COMPLETE;
-                                this.onCompleteObservable.notifyObservers(this);
-                                this.onCompleteObservable.clear();
-                                this._clear();
+                                this._parent._log(`Complete`);
+
+                                this._parent.onCompleteObservable.notifyObservers(undefined);
+                                this._parent.onCompleteObservable.clear();
+                                this.dispose();
                             }).catch(error => {
                             }).catch(error => {
                                 Tools.Error(`glTF Loader: ${error.message}`);
                                 Tools.Error(`glTF Loader: ${error.message}`);
-                                this._clear();
+                                this.dispose();
                             });
                             });
                         }
                         }
                     });
                     });
@@ -286,7 +205,7 @@ module BABYLON.GLTF2 {
             }).catch(error => {
             }).catch(error => {
                 if (!this._disposed) {
                 if (!this._disposed) {
                     Tools.Error(`glTF Loader: ${error.message}`);
                     Tools.Error(`glTF Loader: ${error.message}`);
-                    this._clear();
+                    this.dispose();
                     throw error;
                     throw error;
                 }
                 }
             });
             });
@@ -350,10 +269,10 @@ module BABYLON.GLTF2 {
                 const extension = GLTFLoader._ExtensionFactories[name](this);
                 const extension = GLTFLoader._ExtensionFactories[name](this);
                 this._extensions[name] = extension;
                 this._extensions[name] = extension;
 
 
-                this.onExtensionLoadedObservable.notifyObservers(extension);
+                this._parent.onExtensionLoadedObservable.notifyObservers(extension);
             }
             }
 
 
-            this.onExtensionLoadedObservable.clear();
+            this._parent.onExtensionLoadedObservable.clear();
         }
         }
 
 
         private _checkExtensions(): void {
         private _checkExtensions(): void {
@@ -372,7 +291,7 @@ module BABYLON.GLTF2 {
             this._rootBabylonMesh.setEnabled(false);
             this._rootBabylonMesh.setEnabled(false);
 
 
             const rootNode = { _babylonMesh: this._rootBabylonMesh } as _ILoaderNode;
             const rootNode = { _babylonMesh: this._rootBabylonMesh } as _ILoaderNode;
-            switch (this.coordinateSystemMode) {
+            switch (this._parent.coordinateSystemMode) {
                 case GLTFLoaderCoordinateSystemMode.AUTO: {
                 case GLTFLoaderCoordinateSystemMode.AUTO: {
                     if (!this._babylonScene.useRightHandedSystem) {
                     if (!this._babylonScene.useRightHandedSystem) {
                         rootNode.rotation = [0, 1, 0, 0];
                         rootNode.rotation = [0, 1, 0, 0];
@@ -386,11 +305,11 @@ module BABYLON.GLTF2 {
                     break;
                     break;
                 }
                 }
                 default: {
                 default: {
-                    throw new Error(`Invalid coordinate system mode (${this.coordinateSystemMode})`);
+                    throw new Error(`Invalid coordinate system mode (${this._parent.coordinateSystemMode})`);
                 }
                 }
             }
             }
 
 
-            this.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
+            this._parent.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh);
             return rootNode;
             return rootNode;
         }
         }
 
 
@@ -406,7 +325,6 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        /** @hidden */
         public _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void> {
         public _loadSceneAsync(context: string, scene: _ILoaderScene): Promise<void> {
             const promise = GLTFLoaderExtension._LoadSceneAsync(this, context, scene);
             const promise = GLTFLoaderExtension._LoadSceneAsync(this, context, scene);
             if (promise) {
             if (promise) {
@@ -415,13 +333,19 @@ module BABYLON.GLTF2 {
 
 
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
-            for (let index of scene.nodes) {
-                const node = GLTFLoader._GetProperty(`${context}/nodes/${index}`, this._gltf.nodes, index);
-                promises.push(this._loadNodeAsync(`#/nodes/${node._index}`, node));
+            this._parent._logOpen(`${context} ${scene.name || ""}`);
+
+            if (scene.nodes) {
+                for (let index of scene.nodes) {
+                    const node = GLTFLoader._GetProperty(`${context}/nodes/${index}`, this._gltf.nodes, index);
+                    promises.push(this._loadNodeAsync(`#/nodes/${node._index}`, node));
+                }
             }
             }
 
 
             promises.push(this._loadAnimationsAsync());
             promises.push(this._loadAnimationsAsync());
 
 
+            this._parent._logClose();
+
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
@@ -491,7 +415,7 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         private _startAnimations(): void {
         private _startAnimations(): void {
-            switch (this.animationStartMode) {
+            switch (this._parent.animationStartMode) {
                 case GLTFLoaderAnimationStartMode.NONE: {
                 case GLTFLoaderAnimationStartMode.NONE: {
                     // do nothing
                     // do nothing
                     break;
                     break;
@@ -511,13 +435,12 @@ module BABYLON.GLTF2 {
                     break;
                     break;
                 }
                 }
                 default: {
                 default: {
-                    Tools.Error(`Invalid animation start mode (${this.animationStartMode})`);
+                    Tools.Error(`Invalid animation start mode (${this._parent.animationStartMode})`);
                     return;
                     return;
                 }
                 }
             }
             }
         }
         }
 
 
-        /** @hidden */
         public _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void> {
         public _loadNodeAsync(context: string, node: _ILoaderNode): Promise<void> {
             const promise = GLTFLoaderExtension._LoadNodeAsync(this, context, node);
             const promise = GLTFLoaderExtension._LoadNodeAsync(this, context, node);
             if (promise) {
             if (promise) {
@@ -530,6 +453,8 @@ module BABYLON.GLTF2 {
 
 
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
+            this._parent._logOpen(`${context} ${node.name || ""}`);
+
             const babylonMesh = new Mesh(node.name || `node${node._index}`, this._babylonScene, node._parent ? node._parent._babylonMesh : null);
             const babylonMesh = new Mesh(node.name || `node${node._index}`, this._babylonScene, node._parent ? node._parent._babylonMesh : null);
             node._babylonMesh = babylonMesh;
             node._babylonMesh = babylonMesh;
 
 
@@ -552,7 +477,9 @@ module BABYLON.GLTF2 {
                 }
                 }
             }
             }
 
 
-            this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+            this._parent.onMeshLoadedObservable.notifyObservers(babylonMesh);
+
+            this._parent._logClose();
 
 
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
@@ -560,6 +487,8 @@ module BABYLON.GLTF2 {
         private _loadMeshAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, babylonMesh: Mesh): Promise<void> {
         private _loadMeshAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, babylonMesh: Mesh): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
+            this._parent._logOpen(`${context} ${mesh.name || ""}`);
+
             const primitives = mesh.primitives;
             const primitives = mesh.primitives;
             if (!primitives || primitives.length === 0) {
             if (!primitives || primitives.length === 0) {
                 throw new Error(`${context}: Primitives are missing`);
                 throw new Error(`${context}: Primitives are missing`);
@@ -576,7 +505,7 @@ module BABYLON.GLTF2 {
                     const primitiveBabylonMesh = new Mesh(`${mesh.name || babylonMesh.name}_${primitive._index}`, this._babylonScene, babylonMesh);
                     const primitiveBabylonMesh = new Mesh(`${mesh.name || babylonMesh.name}_${primitive._index}`, this._babylonScene, babylonMesh);
                     node._primitiveBabylonMeshes.push(primitiveBabylonMesh);
                     node._primitiveBabylonMeshes.push(primitiveBabylonMesh);
                     promises.push(this._loadPrimitiveAsync(`${context}/primitives/${primitive._index}`, node, mesh, primitive, primitiveBabylonMesh));
                     promises.push(this._loadPrimitiveAsync(`${context}/primitives/${primitive._index}`, node, mesh, primitive, primitiveBabylonMesh));
-                    this.onMeshLoadedObservable.notifyObservers(babylonMesh);
+                    this._parent.onMeshLoadedObservable.notifyObservers(babylonMesh);
                 }
                 }
             }
             }
 
 
@@ -585,6 +514,8 @@ module BABYLON.GLTF2 {
                 promises.push(this._loadSkinAsync(`#/skins/${skin._index}`, node, mesh, skin));
                 promises.push(this._loadSkinAsync(`#/skins/${skin._index}`, node, mesh, skin));
             }
             }
 
 
+            this._parent._logClose();
+
             return Promise.all(promises).then(() => {
             return Promise.all(promises).then(() => {
                 this._forEachPrimitive(node, babylonMesh => {
                 this._forEachPrimitive(node, babylonMesh => {
                     babylonMesh._refreshBoundingInfo(true);
                     babylonMesh._refreshBoundingInfo(true);
@@ -595,6 +526,8 @@ module BABYLON.GLTF2 {
         private _loadPrimitiveAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<void> {
         private _loadPrimitiveAsync(context: string, node: _ILoaderNode, mesh: _ILoaderMesh, primitive: _ILoaderMeshPrimitive, babylonMesh: Mesh): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
+            this._parent._logOpen(`${context}`);
+
             this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
             this._createMorphTargets(context, node, mesh, primitive, babylonMesh);
             promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(babylonGeometry => {
             promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh).then(babylonGeometry => {
                 return this._loadMorphTargetsAsync(context, primitive, babylonMesh, babylonGeometry).then(() => {
                 return this._loadMorphTargetsAsync(context, primitive, babylonMesh, babylonGeometry).then(() => {
@@ -613,6 +546,8 @@ module BABYLON.GLTF2 {
                 }));
                 }));
             }
             }
 
 
+            this._parent._logClose();
+
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
@@ -920,7 +855,7 @@ module BABYLON.GLTF2 {
                 }
                 }
             }
             }
 
 
-            this.onCameraLoadedObservable.notifyObservers(babylonCamera);
+            this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera);
         }
         }
 
 
         private _loadAnimationsAsync(): Promise<void> {
         private _loadAnimationsAsync(): Promise<void> {
@@ -953,7 +888,7 @@ module BABYLON.GLTF2 {
             }
             }
 
 
             return Promise.all(promises).then(() => {
             return Promise.all(promises).then(() => {
-                babylonAnimationGroup.normalize(this._normalizeAnimationGroupsToBeginAtZero ? 0 : null);
+                babylonAnimationGroup.normalize(this._parent._normalizeAnimationGroupsToBeginAtZero ? 0 : null);
             });
             });
         }
         }
 
 
@@ -1161,7 +1096,6 @@ module BABYLON.GLTF2 {
             return buffer._data;
             return buffer._data;
         }
         }
 
 
-        /** @hidden */
         public _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView> {
         public _loadBufferViewAsync(context: string, bufferView: _ILoaderBufferView): Promise<ArrayBufferView> {
             if (bufferView._data) {
             if (bufferView._data) {
                 return bufferView._data;
                 return bufferView._data;
@@ -1255,7 +1189,6 @@ module BABYLON.GLTF2 {
             return accessor._data as Promise<Float32Array>;
             return accessor._data as Promise<Float32Array>;
         }
         }
 
 
-        /** @hidden */
         public _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer> {
         public _loadVertexBufferViewAsync(context: string, bufferView: _ILoaderBufferView, kind: string): Promise<Buffer> {
             if (bufferView._babylonBuffer) {
             if (bufferView._babylonBuffer) {
                 return bufferView._babylonBuffer;
                 return bufferView._babylonBuffer;
@@ -1297,7 +1230,7 @@ module BABYLON.GLTF2 {
                 babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE;
                 babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE;
                 babylonMaterial.metallic = 1;
                 babylonMaterial.metallic = 1;
                 babylonMaterial.roughness = 1;
                 babylonMaterial.roughness = 1;
-                this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
             }
             }
 
 
             return babylonMaterial;
             return babylonMaterial;
@@ -1345,7 +1278,6 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        /** @hidden */
         public _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void> {
         public _loadMaterialAsync(context: string, material: _ILoaderMaterial, mesh: _ILoaderMesh, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void> {
             const promise = GLTFLoaderExtension._LoadMaterialAsync(this, context, material, mesh, babylonMesh, babylonDrawMode, assign);
             const promise = GLTFLoaderExtension._LoadMaterialAsync(this, context, material, mesh, babylonMesh, babylonDrawMode, assign);
             if (promise) {
             if (promise) {
@@ -1357,13 +1289,15 @@ module BABYLON.GLTF2 {
             if (!babylonData) {
             if (!babylonData) {
                 const promises = new Array<Promise<void>>();
                 const promises = new Array<Promise<void>>();
 
 
+                this._parent._logOpen(`${context} ${material.name || ""}`);
+
                 const name = material.name || `material_${material._index}`;
                 const name = material.name || `material_${material._index}`;
                 const babylonMaterial = this._createMaterial(name, babylonDrawMode);
                 const babylonMaterial = this._createMaterial(name, babylonDrawMode);
 
 
                 promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                 promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                 promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
                 promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
 
 
-                this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+                this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 
 
                 babylonData = {
                 babylonData = {
                     material: babylonMaterial,
                     material: babylonMaterial,
@@ -1372,6 +1306,8 @@ module BABYLON.GLTF2 {
                 };
                 };
 
 
                 material._babylonData[babylonDrawMode] = babylonData;
                 material._babylonData[babylonDrawMode] = babylonData;
+
+                this._parent._logClose();
             }
             }
 
 
             babylonData.meshes.push(babylonMesh);
             babylonData.meshes.push(babylonMesh);
@@ -1380,18 +1316,16 @@ module BABYLON.GLTF2 {
             return babylonData.loaded;
             return babylonData.loaded;
         }
         }
 
 
-        /** @hidden */
         public _createMaterial(name: string, drawMode: number): PBRMaterial {
         public _createMaterial(name: string, drawMode: number): PBRMaterial {
             const babylonMaterial = new PBRMaterial(name, this._babylonScene);
             const babylonMaterial = new PBRMaterial(name, this._babylonScene);
             babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
             babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
             babylonMaterial.fillMode = drawMode;
             babylonMaterial.fillMode = drawMode;
             babylonMaterial.enableSpecularAntiAliasing = true;
             babylonMaterial.enableSpecularAntiAliasing = true;
-            babylonMaterial.useRadianceOverAlpha = !this.transparencyAsCoverage;
-            babylonMaterial.useSpecularOverAlpha = !this.transparencyAsCoverage;
+            babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage;
+            babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage;
             return babylonMaterial;
             return babylonMaterial;
         }
         }
 
 
-        /** @hidden */
         public _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
         public _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
@@ -1433,7 +1367,6 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        /** @hidden */
         public _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void {
         public _loadMaterialAlphaProperties(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): void {
             const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE;
             const alphaMode = material.alphaMode || MaterialAlphaMode.OPAQUE;
             switch (alphaMode) {
             switch (alphaMode) {
@@ -1463,18 +1396,21 @@ module BABYLON.GLTF2 {
             }
             }
         }
         }
 
 
-        /** @hidden */
         public _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void> {
         public _loadTextureAsync(context: string, textureInfo: ITextureInfo, assign: (texture: Texture) => void): Promise<void> {
             const promise = GLTFLoaderExtension._LoadTextureAsync(this, context, textureInfo, assign);
             const promise = GLTFLoaderExtension._LoadTextureAsync(this, context, textureInfo, assign);
             if (promise) {
             if (promise) {
                 return promise;
                 return promise;
             }
             }
 
 
+            this._parent._logOpen(`${context}`);
+
             const texture = GLTFLoader._GetProperty(`${context}/index`, this._gltf.textures, textureInfo.index);
             const texture = GLTFLoader._GetProperty(`${context}/index`, this._gltf.textures, textureInfo.index);
             context = `#/textures/${textureInfo.index}`;
             context = `#/textures/${textureInfo.index}`;
 
 
             const promises = new Array<Promise<void>>();
             const promises = new Array<Promise<void>>();
 
 
+            this._parent._logOpen(`${context} ${texture.name || ""}`);
+
             const sampler = (texture.sampler == undefined ? this._defaultSampler : GLTFLoader._GetProperty(`${context}/sampler`, this._gltf.samplers, texture.sampler));
             const sampler = (texture.sampler == undefined ? this._defaultSampler : GLTFLoader._GetProperty(`${context}/sampler`, this._gltf.samplers, texture.sampler));
             const samplerData = this._loadSampler(`#/samplers/${sampler._index}`, sampler);
             const samplerData = this._loadSampler(`#/samplers/${sampler._index}`, sampler);
 
 
@@ -1502,7 +1438,10 @@ module BABYLON.GLTF2 {
             }));
             }));
 
 
             assign(babylonTexture);
             assign(babylonTexture);
-            this.onTextureLoadedObservable.notifyObservers(babylonTexture);
+            this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture);
+
+            this._parent._logClose();
+            this._parent._logClose();
 
 
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
@@ -1521,27 +1460,28 @@ module BABYLON.GLTF2 {
         }
         }
 
 
         private _loadImageAsync(context: string, image: _ILoaderImage): Promise<Blob> {
         private _loadImageAsync(context: string, image: _ILoaderImage): Promise<Blob> {
-            if (image._blob) {
-                return image._blob;
-            }
+            if (!image._blob) {
+                this._parent._logOpen(`${context} ${image.name || ""}`);
 
 
-            let promise: Promise<ArrayBufferView>;
-            if (image.uri) {
-                promise = this._loadUriAsync(context, image.uri);
-            }
-            else {
-                const bufferView = GLTFLoader._GetProperty(`${context}/bufferView`, this._gltf.bufferViews, image.bufferView);
-                promise = this._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView);
-            }
+                let promise: Promise<ArrayBufferView>;
+                if (image.uri) {
+                    promise = this._loadUriAsync(context, image.uri);
+                }
+                else {
+                    const bufferView = GLTFLoader._GetProperty(`${context}/bufferView`, this._gltf.bufferViews, image.bufferView);
+                    promise = this._loadBufferViewAsync(`#/bufferViews/${bufferView._index}`, bufferView);
+                }
 
 
-            image._blob = promise.then(data => {
-                return new Blob([data], { type: image.mimeType });
-            });
+                image._blob = promise.then(data => {
+                    return new Blob([data], { type: image.mimeType });
+                });
+
+                this._parent._logClose();
+            }
 
 
             return image._blob;
             return image._blob;
         }
         }
 
 
-        /** @hidden */
         public _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView> {
         public _loadUriAsync(context: string, uri: string): Promise<ArrayBufferView> {
             const promise = GLTFLoaderExtension._LoadUriAsync(this, context, uri);
             const promise = GLTFLoaderExtension._LoadUriAsync(this, context, uri);
             if (promise) {
             if (promise) {
@@ -1553,28 +1493,37 @@ module BABYLON.GLTF2 {
             }
             }
 
 
             if (Tools.IsBase64(uri)) {
             if (Tools.IsBase64(uri)) {
-                return Promise.resolve(new Uint8Array(Tools.DecodeBase64(uri)));
+                const data = new Uint8Array(Tools.DecodeBase64(uri));
+                this._parent._log(`Decoded ${uri.substr(0, 64)}... (${data.length} bytes)`);
+                return Promise.resolve(data);
             }
             }
 
 
-            return this.preprocessUrlAsync(this._rootUrl + uri).then(url => {
+            this._parent._log(`Loading ${uri}`);
+
+            return this._parent.preprocessUrlAsync(this._rootUrl + uri).then(url => {
                 return new Promise<ArrayBufferView>((resolve, reject) => {
                 return new Promise<ArrayBufferView>((resolve, reject) => {
                     if (!this._disposed) {
                     if (!this._disposed) {
-                        const request = Tools.LoadFile(url, data => {
+                        const request = Tools.LoadFile(url, fileData => {
                             if (!this._disposed) {
                             if (!this._disposed) {
-                                resolve(new Uint8Array(data as ArrayBuffer));
+                                const data = new Uint8Array(fileData as ArrayBuffer);
+                                this._parent._log(`Loaded ${uri} (${data.length} bytes)`);
+                                resolve(data);
                             }
                             }
                         }, event => {
                         }, event => {
                             if (!this._disposed) {
                             if (!this._disposed) {
-                                try {
-                                    if (request && this._state === GLTFLoaderState.LOADING) {
-                                        request._lengthComputable = event.lengthComputable;
-                                        request._loaded = event.loaded;
-                                        request._total = event.total;
+                                if (request) {
+                                    request._lengthComputable = event.lengthComputable;
+                                    request._loaded = event.loaded;
+                                    request._total = event.total;
+                                }
+
+                                if (this._state === GLTFLoaderState.LOADING) {
+                                    try {
                                         this._onProgress();
                                         this._onProgress();
                                     }
                                     }
-                                }
-                                catch (e) {
-                                    reject(e);
+                                    catch (e) {
+                                        reject(e);
+                                    }
                                 }
                                 }
                             }
                             }
                         }, this._babylonScene.database, true, (request, exception) => {
                         }, this._babylonScene.database, true, (request, exception) => {
@@ -1610,7 +1559,6 @@ module BABYLON.GLTF2 {
             this._progressCallback(new SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
             this._progressCallback(new SceneLoaderProgressEvent(lengthComputable, loaded, lengthComputable ? total : 0));
         }
         }
 
 
-        /** @hidden */
         public static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T {
         public static _GetProperty<T>(context: string, array: ArrayLike<T> | undefined, index: number | undefined): T {
             if (!array || index == undefined || !array[index]) {
             if (!array || index == undefined || !array[index]) {
                 throw new Error(`${context}: Failed to find index (${index})`);
                 throw new Error(`${context}: Failed to find index (${index})`);
@@ -1740,7 +1688,7 @@ module BABYLON.GLTF2 {
 
 
                                 const babylonMaterial = babylonData.material;
                                 const babylonMaterial = babylonData.material;
                                 promises.push(babylonMaterial.forceCompilationAsync(babylonMesh));
                                 promises.push(babylonMaterial.forceCompilationAsync(babylonMesh));
-                                if (this.useClipPlane) {
+                                if (this._parent.useClipPlane) {
                                     promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true }));
                                     promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true }));
                                 }
                                 }
                             }
                             }
@@ -1766,35 +1714,7 @@ module BABYLON.GLTF2 {
             return Promise.all(promises).then(() => {});
             return Promise.all(promises).then(() => {});
         }
         }
 
 
-        private _clear(): void {
-            for (const request of this._requests) {
-                request.abort();
-            }
-
-            this._requests.length = 0;
-
-            delete this._gltf;
-            delete this._babylonScene;
-            this._completePromises.length = 0;
-            this._onReadyObservable.clear();
-
-            for (const name in this._extensions) {
-                this._extensions[name].dispose();
-            }
-
-            this._extensions = {};
-
-            delete this._rootBabylonMesh;
-            delete this._progressCallback;
-
-            this.onMeshLoadedObservable.clear();
-            this.onTextureLoadedObservable.clear();
-            this.onMaterialLoadedObservable.clear();
-            this.onCameraLoadedObservable.clear();
-        }
-
-        /** @hidden */
-        public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {
+        public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>): Nullable<Promise<T>> {
             for (const name of GLTFLoader._ExtensionNames) {
             for (const name of GLTFLoader._ExtensionNames) {
                 const extension = this._extensions[name];
                 const extension = this._extensions[name];
                 if (extension.enabled) {
                 if (extension.enabled) {
@@ -1809,5 +1729,5 @@ module BABYLON.GLTF2 {
         }
         }
     }
     }
 
 
-    GLTFFileLoader._CreateGLTFLoaderV2 = () => new GLTFLoader();
+    GLTFFileLoader._CreateGLTFLoaderV2 = parent => new GLTFLoader(parent);
 }
 }

+ 1 - 1
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -1,5 +1,5 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     /** @hidden */
     /** @hidden */

+ 88 - 139
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -86,101 +86,10 @@ module BABYLON {
         COMPLETE
         COMPLETE
     }
     }
 
 
-    /**
-     * Loader interface.
-     */
+    /** @hidden */
     export interface IGLTFLoader extends IDisposable {
     export interface IGLTFLoader extends IDisposable {
-        /**
-         * Mode that determines the coordinate system to use.
-         */
-        coordinateSystemMode: GLTFLoaderCoordinateSystemMode;
-
-        /**
-         * Mode that determines what animations will start.
-         */
-        animationStartMode: GLTFLoaderAnimationStartMode;
-
-        /**
-         * Defines if the loader should compile materials.
-         */
-        compileMaterials: boolean;
-
-        /**
-         * Defines if the loader should also compile materials with clip planes.
-         */
-        useClipPlane: boolean;
-
-        /**
-         * Defines if the loader should compile shadow generators.
-         */
-        compileShadowGenerators: boolean;
-
-        /**
-         * Defines if the Alpha blended materials are only applied as coverage. 
-         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
-         * If true, no extra effects are applied to transparent pixels.
-         */
-        transparencyAsCoverage: boolean;
-
-        /** @hidden */
-        _normalizeAnimationGroupsToBeginAtZero: boolean;
-
-        /**
-         * Function called before loading a url referenced by the asset.
-         */
-        preprocessUrlAsync: (url: string) => Promise<string>;
-
-        /**
-         * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
-         */
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-
-        /**
-         * Observable raised when the loader creates a texture after parsing the glTF properties of the texture.
-         */
-        onTextureLoadedObservable: Observable<BaseTexture>;
-
-        /**
-         * Observable raised when the loader creates a material after parsing the glTF properties of the material.
-         */
-        onMaterialLoadedObservable: Observable<Material>;
-
-        /**
-         * Observable raised when the loader creates a camera after parsing the glTF properties of the camera.
-         */
-        onCameraLoadedObservable: Observable<Camera>;
-
-        /**
-         * Observable raised when the asset is completely loaded, immediately before the loader is disposed.
-         * For assets with LODs, raised when all of the LODs are complete.
-         * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
-         */
-        onCompleteObservable: Observable<IGLTFLoader>;
-
-        /**
-         * Observable raised after the loader is disposed.
-         */
-        onDisposeObservable: Observable<IGLTFLoader>;
-
-        /**
-         * Observable raised after a loader extension is created.
-         * Set additional options for a loader extension in this event.
-         */
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-
-        /**
-         * Loader state or null if the loader is not active.
-         */
-        state: Nullable<GLTFLoaderState>;
-
-        /**
-         * Imports meshes from the given data and adds them to the scene.
-         */
+        readonly state: Nullable<GLTFLoaderState>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
         importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<{ meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }>;
-
-        /**
-         * Loads all objects from the given data and adds them to the scene.
-         */
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void) => Promise<void>;
     }
     }
 
 
@@ -189,10 +98,10 @@ module BABYLON {
      */
      */
     export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
     export class GLTFFileLoader implements IDisposable, ISceneLoaderPluginAsync, ISceneLoaderPluginFactory {
         /** @hidden */
         /** @hidden */
-        public static _CreateGLTFLoaderV1: () => IGLTFLoader;
+        public static _CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
 
 
         /** @hidden */
         /** @hidden */
-        public static _CreateGLTFLoaderV2: () => IGLTFLoader;
+        public static _CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
 
 
         // #region Common options
         // #region Common options
 
 
@@ -272,6 +181,39 @@ module BABYLON {
         public _normalizeAnimationGroupsToBeginAtZero = true;
         public _normalizeAnimationGroupsToBeginAtZero = true;
 
 
         /**
         /**
+         * Defines if the loader logging is enabled.
+         */
+        public loggingEnabled = false;
+
+        /**
+         * Observable raised when the loader logs a message.
+         */
+        public readonly onLogObservable = new Observable<string>();
+
+        private _logIndentLevel = 0;
+        private static readonly _logSpaces = "                                ";
+
+        /** @hidden */
+        public _log(message: string): void {
+            if (this.loggingEnabled) {
+                const spaces = GLTFFileLoader._logSpaces.substr(0, this._logIndentLevel * 2);
+                this.onLogObservable.notifyObservers(`${spaces}${message}`);
+                Tools.Log(`${spaces}${message}`);
+            }
+        }
+
+        /** @hidden */
+        public _logOpen(message: string): void {
+            this._log(message);
+            this._logIndentLevel++;
+        }
+
+        /** @hidden */
+        public _logClose(): void {
+            --this._logIndentLevel;
+        }
+
+        /**
          * Function called before loading a url referenced by the asset.
          * Function called before loading a url referenced by the asset.
          */
          */
         public preprocessUrlAsync = (url: string) => Promise.resolve(url);
         public preprocessUrlAsync = (url: string) => Promise.resolve(url);
@@ -349,9 +291,9 @@ module BABYLON {
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets with LODs, raised when all of the LODs are complete.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise.
          */
          */
-        public readonly onCompleteObservable = new Observable<GLTFFileLoader>();
+        public readonly onCompleteObservable = new Observable<void>();
 
 
-        private _onCompleteObserver: Nullable<Observer<GLTFFileLoader>>;
+        private _onCompleteObserver: Nullable<Observer<void>>;
 
 
         /**
         /**
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
          * Callback raised when the asset is completely loaded, immediately before the loader is disposed.
@@ -366,9 +308,9 @@ module BABYLON {
         /**
         /**
          * Observable raised after the loader is disposed.
          * Observable raised after the loader is disposed.
          */
          */
-        public readonly onDisposeObservable = new Observable<GLTFFileLoader>();
+        public readonly onDisposeObservable = new Observable<void>();
 
 
-        private _onDisposeObserver: Nullable<Observer<GLTFFileLoader>>;
+        private _onDisposeObserver: Nullable<Observer<void>>;
 
 
         /**
         /**
          * Callback raised after the loader is disposed.
          * Callback raised after the loader is disposed.
@@ -443,6 +385,14 @@ module BABYLON {
                 this._loader = null;
                 this._loader = null;
             }
             }
 
 
+            this._clear();
+
+            this.onDisposeObservable.notifyObservers(undefined);
+            this.onDisposeObservable.clear();
+        }
+
+        /** @hidden */
+        public _clear(): void {
             this.preprocessUrlAsync = url => Promise.resolve(url);
             this.preprocessUrlAsync = url => Promise.resolve(url);
 
 
             this.onMeshLoadedObservable.clear();
             this.onMeshLoadedObservable.clear();
@@ -451,9 +401,6 @@ module BABYLON {
             this.onCameraLoadedObservable.clear();
             this.onCameraLoadedObservable.clear();
             this.onCompleteObservable.clear();
             this.onCompleteObservable.clear();
             this.onExtensionLoadedObservable.clear();
             this.onExtensionLoadedObservable.clear();
-
-            this.onDisposeObservable.notifyObservers(this);
-            this.onDisposeObservable.clear();
         }
         }
 
 
         /**
         /**
@@ -538,9 +485,18 @@ module BABYLON {
         private _parse(data: string | ArrayBuffer): IGLTFLoaderData {
         private _parse(data: string | ArrayBuffer): IGLTFLoaderData {
             let parsedData: IGLTFLoaderData;
             let parsedData: IGLTFLoaderData;
             if (data instanceof ArrayBuffer) {
             if (data instanceof ArrayBuffer) {
-                parsedData = GLTFFileLoader._parseBinary(data);
+                if (this.loggingEnabled) {
+                    this._log(`Parsing binary`);
+                }
+
+                parsedData = this._parseBinary(data);
             }
             }
             else {
             else {
+                if (this.loggingEnabled) {
+                    this._log(`Parsing JSON`);
+                    this._log(`JSON length: ${data.length}`);
+                }
+
                 parsedData = {
                 parsedData = {
                     json: JSON.parse(data),
                     json: JSON.parse(data),
                     bin: null
                     bin: null
@@ -554,10 +510,20 @@ module BABYLON {
         }
         }
 
 
         private _getLoader(loaderData: IGLTFLoaderData): IGLTFLoader {
         private _getLoader(loaderData: IGLTFLoaderData): IGLTFLoader {
-            const loaderVersion = { major: 2, minor: 0 };
-
             const asset = (<any>loaderData.json).asset || {};
             const asset = (<any>loaderData.json).asset || {};
 
 
+            if (this.loggingEnabled) {
+                this._log(`Asset version: ${asset.version}`);
+
+                if (asset.minVersion) {
+                    this._log(`Asset minimum version: ${asset.minVersion}`);
+                }
+
+                if (asset.generator) {
+                    this._log(`Asset generator: ${asset.generator}`);
+                }
+            }
+
             const version = GLTFFileLoader._parseVersion(asset.version);
             const version = GLTFFileLoader._parseVersion(asset.version);
             if (!version) {
             if (!version) {
                 throw new Error("Invalid version: " + asset.version);
                 throw new Error("Invalid version: " + asset.version);
@@ -569,12 +535,12 @@ module BABYLON {
                     throw new Error("Invalid minimum version: " + asset.minVersion);
                     throw new Error("Invalid minimum version: " + asset.minVersion);
                 }
                 }
 
 
-                if (GLTFFileLoader._compareVersion(minVersion, loaderVersion) > 0) {
+                if (GLTFFileLoader._compareVersion(minVersion, { major: 2, minor: 0 }) > 0) {
                     throw new Error("Incompatible minimum version: " + asset.minVersion);
                     throw new Error("Incompatible minimum version: " + asset.minVersion);
                 }
                 }
             }
             }
 
 
-            const createLoaders: { [key: number]: () => IGLTFLoader } = {
+            const createLoaders: { [key: number]: (parent: GLTFFileLoader) => IGLTFLoader } = {
                 1: GLTFFileLoader._CreateGLTFLoaderV1,
                 1: GLTFFileLoader._CreateGLTFLoaderV1,
                 2: GLTFFileLoader._CreateGLTFLoaderV2
                 2: GLTFFileLoader._CreateGLTFLoaderV2
             };
             };
@@ -584,40 +550,18 @@ module BABYLON {
                 throw new Error("Unsupported version: " + asset.version);
                 throw new Error("Unsupported version: " + asset.version);
             }
             }
 
 
-            const loader = createLoader();
-            loader.coordinateSystemMode = this.coordinateSystemMode;
-            loader.animationStartMode = this.animationStartMode;
-            loader.compileMaterials = this.compileMaterials;
-            loader.useClipPlane = this.useClipPlane;
-            loader.compileShadowGenerators = this.compileShadowGenerators;
-            loader.transparencyAsCoverage = this.transparencyAsCoverage;
-            loader._normalizeAnimationGroupsToBeginAtZero = this._normalizeAnimationGroupsToBeginAtZero;
-            loader.preprocessUrlAsync = this.preprocessUrlAsync;
-            loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
-            loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
-            loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));
-            loader.onCameraLoadedObservable.add(camera => this.onCameraLoadedObservable.notifyObservers(camera));
-            loader.onExtensionLoadedObservable.add(extension => this.onExtensionLoadedObservable.notifyObservers(extension));
-
-            loader.onCompleteObservable.add(() => {
-                this.onMeshLoadedObservable.clear();
-                this.onTextureLoadedObservable.clear();
-                this.onMaterialLoadedObservable.clear();
-                this.onCameraLoadedObservable.clear();
-                this.onExtensionLoadedObservable.clear();
-
-                this.onCompleteObservable.notifyObservers(this);
-                this.onCompleteObservable.clear();
-            });
-
-            return loader;
+            return createLoader(this);
         }
         }
 
 
-        private static _parseBinary(data: ArrayBuffer): IGLTFLoaderData {
+        private _parseBinary(data: ArrayBuffer): IGLTFLoaderData {
             const Binary = {
             const Binary = {
                 Magic: 0x46546C67
                 Magic: 0x46546C67
             };
             };
 
 
+            if (this.loggingEnabled) {
+                this._log(`Binary length: ${data.byteLength}`);
+            }
+
             const binaryReader = new BinaryReader(data);
             const binaryReader = new BinaryReader(data);
 
 
             const magic = binaryReader.readUint32();
             const magic = binaryReader.readUint32();
@@ -626,15 +570,20 @@ module BABYLON {
             }
             }
 
 
             const version = binaryReader.readUint32();
             const version = binaryReader.readUint32();
+
+            if (this.loggingEnabled) {
+                this._log(`Binary version: ${version}`);
+            }
+
             switch (version) {
             switch (version) {
-                case 1: return GLTFFileLoader._parseV1(binaryReader);
-                case 2: return GLTFFileLoader._parseV2(binaryReader);
+                case 1: return this._parseV1(binaryReader);
+                case 2: return this._parseV2(binaryReader);
             }
             }
 
 
             throw new Error("Unsupported version: " + version);
             throw new Error("Unsupported version: " + version);
         }
         }
 
 
-        private static _parseV1(binaryReader: BinaryReader): IGLTFLoaderData {
+        private _parseV1(binaryReader: BinaryReader): IGLTFLoaderData {
             const ContentFormat = {
             const ContentFormat = {
                 JSON: 0
                 JSON: 0
             };
             };
@@ -667,7 +616,7 @@ module BABYLON {
             };
             };
         }
         }
 
 
-        private static _parseV2(binaryReader: BinaryReader): IGLTFLoaderData {
+        private _parseV2(binaryReader: BinaryReader): IGLTFLoaderData {
             const ChunkFormat = {
             const ChunkFormat = {
                 JSON: 0x4E4F534A,
                 JSON: 0x4E4F534A,
                 BIN: 0x004E4942
                 BIN: 0x004E4942

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFAnimation.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     /**
     /**

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFData.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 
 module BABYLON {
 module BABYLON {
     /**
     /**

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     /** 
     /** 

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFMaterial.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     /** 
     /** 

+ 1 - 1
serializers/src/glTF/2.0/babylon.glTFUtilities.ts

@@ -1,4 +1,4 @@
-/// <reference path="../../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 
 
 module BABYLON.GLTF2 {
 module BABYLON.GLTF2 {
     /**
     /**

+ 1 - 1
tests/unit/babylon/babylonReference.ts

@@ -1,6 +1,6 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 /// <reference path="../../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts" />
 /// <reference path="../../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts" />
-/// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts" />
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts" />
 
 
 /// <reference path="../node_modules/@types/chai/index.d.ts" />
 /// <reference path="../node_modules/@types/chai/index.d.ts" />