Просмотр исходного кода

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

sebavan 5 лет назад
Родитель
Сommit
ce72b9dc0a
39 измененных файлов с 1270 добавлено и 309 удалено
  1. 17 4
      Playground/js/monacoCreator.js
  2. 65 0
      Playground/js/utils.js
  3. 1 1
      dist/preview release/babylon.d.ts
  4. 1 1
      dist/preview release/babylon.js
  5. 27 33
      dist/preview release/babylon.max.js
  6. 1 1
      dist/preview release/babylon.max.js.map
  7. 2 2
      dist/preview release/babylon.module.d.ts
  8. 76 21
      dist/preview release/documentation.d.ts
  9. 5 1
      dist/preview release/gui/babylon.gui.d.ts
  10. 70 13
      dist/preview release/gui/babylon.gui.js
  11. 1 1
      dist/preview release/gui/babylon.gui.js.map
  12. 1 1
      dist/preview release/gui/babylon.gui.min.js
  13. 10 2
      dist/preview release/gui/babylon.gui.module.d.ts
  14. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  15. 4 0
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  16. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  17. 1 1
      dist/preview release/packagesSizeBaseLine.json
  18. 224 41
      dist/preview release/serializers/babylon.glTF2Serializer.js
  19. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.js.map
  20. 2 2
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  21. 1 1
      dist/preview release/serializers/babylon.objSerializer.min.js
  22. 70 19
      dist/preview release/serializers/babylonjs.serializers.d.ts
  23. 233 44
      dist/preview release/serializers/babylonjs.serializers.js
  24. 1 1
      dist/preview release/serializers/babylonjs.serializers.js.map
  25. 2 2
      dist/preview release/serializers/babylonjs.serializers.min.js
  26. 152 43
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  27. 2 2
      dist/preview release/viewer/babylon.module.d.ts
  28. 6 6
      dist/preview release/viewer/babylon.viewer.js
  29. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  30. 3 0
      nodeEditor/src/components/propertyTab/propertyTabComponent.tsx
  31. 1 2
      serializers/src/glTF/2.0/Extensions/KHR_lights_punctual.ts
  32. 115 0
      serializers/src/glTF/2.0/Extensions/KHR_materials_sheen.ts
  33. 19 3
      serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts
  34. 2 1
      serializers/src/glTF/2.0/Extensions/index.ts
  35. 76 35
      serializers/src/glTF/2.0/glTFExporter.ts
  36. 32 7
      serializers/src/glTF/2.0/glTFExporterExtension.ts
  37. 40 9
      serializers/src/glTF/2.0/glTFMaterialExporter.ts
  38. 2 4
      src/Gamepads/Controllers/windowsMotionController.ts
  39. 1 1
      src/Meshes/mesh.ts

+ 17 - 4
Playground/js/monacoCreator.js

@@ -54,10 +54,21 @@ class MonacoCreator {
      */
     async loadMonaco(typings) {
         let response = await fetch(typings || "https://preview.babylonjs.com/babylon.d.ts");
-        if (!response.ok)
+        if (!response.ok) {
             return;
+        }
+
+        let libContent = await response.text();
+
+        if (!typings) {
+            response = await fetch(typings || "https://preview.babylonjs.com/gui/babylon.gui.d.ts");
+            if (!response.ok) {
+                return;
+            }
+
+            libContent += await response.text();
+        }
 
-        const libContent = await response.text();
         this.setupDefinitionWorker(libContent);
 
         require.config({ paths: { 'vs': 'node_modules/monaco-editor/dev/vs' } });
@@ -290,11 +301,13 @@ class MonacoCreator {
         };
         editorOptions.minimap.enabled = document.getElementById("minimapToggle1280").classList.contains('checked');
         this.jsEditor = monaco.editor.create(document.getElementById('jsEditor'), editorOptions);
-
         this.jsEditor.setValue(oldCode);
+
+        const analyzeCodeDebounced = this.parent.utils.debounceAsync((async) => this.analyzeCode(), 500);
+
         this.jsEditor.onDidChangeModelContent(function () {
             this.parent.utils.markDirty();
-            this.analyzeCode();
+            analyzeCodeDebounced();
         }.bind(this));
     };
 

+ 65 - 0
Playground/js/utils.js

@@ -119,4 +119,69 @@ class Utils {
             if(document.getElementById("menuButton" + this.multipleSize[i]).offsetHeight > 0) return this.multipleSize[i];
         }
     };
+
+    debounceAsync(fn, wait = 0, options = {}) {
+        let lastCallAt
+        let deferred
+        let timer
+        let pendingArgs = []
+        return function debounced(...args) {
+            const currentWait = getWait(wait)
+            const currentTime = new Date().getTime()
+
+            const isCold = !lastCallAt || (currentTime - lastCallAt) > currentWait
+
+            lastCallAt = currentTime
+
+            if (isCold && options.leading) {
+                return options.accumulate
+                    ? Promise.resolve(fn.call(this, [args])).then(result => result[0])
+                    : Promise.resolve(fn.call(this, ...args))
+            }
+
+            if (deferred) {
+                clearTimeout(timer)
+            } else {
+                deferred = defer()
+            }
+
+            pendingArgs.push(args)
+            timer = setTimeout(flush.bind(this), currentWait)
+
+            if (options.accumulate) {
+                const argsIndex = pendingArgs.length - 1
+                return deferred.promise.then(results => results[argsIndex])
+            }
+
+            return deferred.promise
+        }
+
+        function getWait(wait) {
+            return (typeof wait === 'function') ? wait() : wait
+        }
+    
+        function defer() {
+            const deferred = {}
+            deferred.promise = new Promise((resolve, reject) => {
+                deferred.resolve = resolve
+                deferred.reject = reject
+            })
+            return deferred
+        }
+
+        function flush() {
+            const thisDeferred = deferred
+            clearTimeout(timer)
+
+            Promise.resolve(
+                options.accumulate
+                    ? fn.call(this, pendingArgs)
+                    : fn.apply(this, pendingArgs[pendingArgs.length - 1])
+            )
+                .then(thisDeferred.resolve, thisDeferred.reject)
+
+            pendingArgs = []
+            deferred = null
+        }
+    }    
 }

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

@@ -42636,7 +42636,7 @@ declare module BABYLON {
         /**
          * holds the thumbstick values (X,Y)
          */
-        readonly thumbstickValues: StickValues;
+        thumbstickValues: StickValues;
         /**
          * Fired when the thumbstick on this controller is clicked
          */

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/babylon.js


Разница между файлами не показана из-за своего большого размера
+ 27 - 33
dist/preview release/babylon.max.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 2 - 2
dist/preview release/babylon.module.d.ts

@@ -44142,7 +44142,7 @@ declare module "babylonjs/Gamepads/Controllers/windowsMotionController" {
         /**
          * holds the thumbstick values (X,Y)
          */
-        readonly thumbstickValues: StickValues;
+        thumbstickValues: StickValues;
         /**
          * Fired when the thumbstick on this controller is clicked
          */
@@ -111549,7 +111549,7 @@ declare module BABYLON {
         /**
          * holds the thumbstick values (X,Y)
          */
-        readonly thumbstickValues: StickValues;
+        thumbstickValues: StickValues;
         /**
          * Fired when the thumbstick on this controller is clicked
          */

+ 76 - 21
dist/preview release/documentation.d.ts

@@ -42636,7 +42636,7 @@ declare module BABYLON {
         /**
          * holds the thumbstick values (X,Y)
          */
-        readonly thumbstickValues: StickValues;
+        thumbstickValues: StickValues;
         /**
          * Fired when the thumbstick on this controller is clicked
          */
@@ -67360,6 +67360,8 @@ declare module BABYLON.GUI {
         autoScale: boolean;
         /** Gets or sets the streching mode used by the image */
         stretch: number;
+        /** @hidden */
+        _rotate90(n: number): Image;
         /**
          * Gets or sets the internal DOM image used to render the control
          */
@@ -68609,14 +68611,16 @@ declare module BABYLON.GUI {
      */
     export class ImageScrollBar extends BaseSlider {
         name?: string | undefined;
+        private _backgroundBaseImage;
         private _backgroundImage;
         private _thumbImage;
+        private _thumbBaseImage;
         private _thumbLength;
         private _thumbHeight;
         private _barImageHeight;
         private _tempMeasure;
         /**
-         * Gets or sets the image used to render the background
+         * Gets or sets the image used to render the background for horizontal bar
          */
         backgroundImage: Image;
         /**
@@ -71924,11 +71928,18 @@ declare module BABYLON.GLTF2.Exporter {
         /**
          * Define this method to modify the default behavior before exporting a texture
          * @param context The context when loading the asset
-         * @param babylonTexture The glTF texture info property
+         * @param babylonTexture The Babylon.js texture
          * @param mimeType The mime-type of the generated image
-         * @returns A promise that resolves with the exported glTF texture info when the export is complete, or null if not handled
+         * @returns A promise that resolves with the exported texture
+         */
+        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
+        /**
+         * Define this method to get notified when a texture info is created
+         * @param context The context when loading the asset
+         * @param textureInfo The glTF texture info
+         * @param babylonTexture The Babylon.js texture
          */
-        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         /**
          * Define this method to modify the default behavior when exporting texture info
          * @param context The context when loading the asset
@@ -71937,7 +71948,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param binaryWriter glTF serializer binary writer instance
          * @returns nullable IMeshPrimitive promise
          */
-        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<IMeshPrimitive>;
         /**
          * Define this method to modify the default behavior when exporting a node
          * @param context The context when exporting the node
@@ -71945,7 +71956,21 @@ declare module BABYLON.GLTF2.Exporter {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Promise<INode>;
+        /**
+         * Define this method to modify the default behavior when exporting a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns nullable IMaterial promise
+         */
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
+        /**
+         * Defint this method to return additional textures to export from a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns List of textures
+         */
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
         /**
          * Called after the exporter state changes to EXPORTING
          */
@@ -72039,7 +72064,8 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
+        private _finishMaterial;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
@@ -72050,7 +72076,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         /**
          * Converts an image typed array buffer to a base64 image
          * @param buffer typed array buffer
@@ -72149,7 +72175,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         private setMetallicRoughnessPbrMaterial;
         private getPixelsFromTexture;
         /**
@@ -72431,10 +72457,14 @@ declare module BABYLON.GLTF2.Exporter {
         private _extensions;
         private static _ExtensionNames;
         private static _ExtensionFactories;
+        private _applyExtension;
         private _applyExtensions;
-        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>>;
-        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
-        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Nullable<BaseTexture>>;
+        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<Nullable<IMeshPrimitive>>;
+        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<Nullable<INode>>;
+        _extensionsPostExportMaterialAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<Nullable<IMaterial>>;
+        _extensionsPostExportMaterialAdditionalTextures(context: string, material: IMaterial, babylonMaterial: Material): BaseTexture[];
+        _extensionsPostExportTextures(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         private _forEachExtensions;
         private _extensionsOnExporting;
         /**
@@ -72447,6 +72477,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param options Options to modify the behavior of the exporter
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
+        dispose(): void;
         /**
          * Registers a glTF exporter extension
          * @param name Name of the extension to export
@@ -72541,9 +72572,10 @@ declare module BABYLON.GLTF2.Exporter {
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix Text to use when prefixing a glTF file
+         * @param dispose Dispose the exporter
          * @returns GLTFData with glTF file data
          */
-        _generateGLTFAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLTFAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Creates a binary buffer for glTF
          * @returns array buffer for binary data
@@ -72556,12 +72588,9 @@ declare module BABYLON.GLTF2.Exporter {
          */
         private _getPadding;
         /**
-         * Generates a glb file from the json and binary data
-         * Returns an object with the glb file name as the key and data as the value
-         * @param glTFPrefix
-         * @returns object with glb filename as key and data as value
+         * @hidden
          */
-        _generateGLBAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLBAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Sets the TRS for each node
          * @param node glTF Node for storing the transformation data
@@ -72877,6 +72906,7 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
      * @hidden
      */
     export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
+        private _recordedTextures;
         /** Name of this extension */
         readonly name: string;
         /** Defines whether this extension is enabled */
@@ -72887,7 +72917,7 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
         private _exporter;
         constructor(exporter: _Exporter);
         dispose(): void;
-        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
         /**
          * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
          * @param babylonTexture
@@ -72926,7 +72956,32 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<INode>;
+    }
+}
+declare module BABYLON.GLTF2.Exporter.Extensions {
+    /**
+     * @hidden
+     */
+    export class KHR_materials_sheen implements IGLTFExporterExtensionV2 {
+        /** Name of this extension */
+        readonly name: string;
+        /** Defines whether this extension is enabled */
+        enabled: boolean;
+        /** Defines whether this extension is required */
+        required: boolean;
+        /** Reference to the glTF exporter */
+        private _exporter;
+        private _textureInfo;
+        private _exportedTexture;
+        private _wasUsed;
+        constructor(exporter: _Exporter);
+        dispose(): void;
+        /** @hidden */
+        onExporting(): void;
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void;
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
     }
 }
 declare module BABYLON {

+ 5 - 1
dist/preview release/gui/babylon.gui.d.ts

@@ -1501,6 +1501,8 @@ declare module BABYLON.GUI {
         autoScale: boolean;
         /** Gets or sets the streching mode used by the image */
         stretch: number;
+        /** @hidden */
+        _rotate90(n: number): Image;
         /**
          * Gets or sets the internal DOM image used to render the control
          */
@@ -2750,14 +2752,16 @@ declare module BABYLON.GUI {
      */
     export class ImageScrollBar extends BaseSlider {
         name?: string | undefined;
+        private _backgroundBaseImage;
         private _backgroundImage;
         private _thumbImage;
+        private _thumbBaseImage;
         private _thumbLength;
         private _thumbHeight;
         private _barImageHeight;
         private _tempMeasure;
         /**
-         * Gets or sets the image used to render the background
+         * Gets or sets the image used to render the background for horizontal bar
          */
         backgroundImage: Image;
         /**

+ 70 - 13
dist/preview release/gui/babylon.gui.js

@@ -6565,6 +6565,21 @@ var Image = /** @class */ (function (_super) {
         enumerable: true,
         configurable: true
     });
+    /** @hidden */
+    Image.prototype._rotate90 = function (n) {
+        var canvas = document.createElement('canvas');
+        var context = canvas.getContext('2d');
+        var width = this._domImage.width;
+        var height = this._domImage.height;
+        canvas.width = height;
+        canvas.height = width;
+        context.translate(canvas.width / 2, canvas.height / 2);
+        context.rotate(n * Math.PI / 2);
+        context.drawImage(this._domImage, 0, 0, width, height, -width / 2, -height / 2, width, height);
+        var dataUrl = canvas.toDataURL("image/jpg");
+        var rotatedImage = new Image(this.name + "rotated", dataUrl);
+        return rotatedImage;
+    };
     Object.defineProperty(Image.prototype, "domImage", {
         get: function () {
             return this._domImage;
@@ -10837,21 +10852,42 @@ var ImageScrollBar = /** @class */ (function (_super) {
     }
     Object.defineProperty(ImageScrollBar.prototype, "backgroundImage", {
         /**
-         * Gets or sets the image used to render the background
+         * Gets or sets the image used to render the background for horizontal bar
          */
         get: function () {
-            return this._backgroundImage;
+            return this._backgroundBaseImage;
         },
         set: function (value) {
             var _this = this;
-            if (this._backgroundImage === value) {
+            if (this._backgroundBaseImage === value) {
                 return;
             }
-            this._backgroundImage = value;
-            if (value && !value.isLoaded) {
-                value.onImageLoadedObservable.addOnce(function () { return _this._markAsDirty(); });
+            this._backgroundBaseImage = value;
+            if (this.isVertical) {
+                if (value && !value.isLoaded) {
+                    value.onImageLoadedObservable.addOnce(function () {
+                        var rotatedValue = value._rotate90(1);
+                        _this._backgroundImage = rotatedValue;
+                        if (!rotatedValue.isLoaded) {
+                            rotatedValue.onImageLoadedObservable.addOnce(function () {
+                                _this._markAsDirty();
+                            });
+                        }
+                        _this._markAsDirty();
+                    });
+                }
+                this._backgroundImage = value._rotate90(1);
+                this._markAsDirty();
+            }
+            else {
+                this._backgroundImage = value;
+                if (value && !value.isLoaded) {
+                    value.onImageLoadedObservable.addOnce(function () {
+                        _this._markAsDirty();
+                    });
+                }
+                this._markAsDirty();
             }
-            this._markAsDirty();
         },
         enumerable: true,
         configurable: true
@@ -10861,18 +10897,39 @@ var ImageScrollBar = /** @class */ (function (_super) {
          * Gets or sets the image used to render the thumb
          */
         get: function () {
-            return this._thumbImage;
+            return this._thumbBaseImage;
         },
         set: function (value) {
             var _this = this;
-            if (this._thumbImage === value) {
+            if (this._thumbBaseImage === value) {
                 return;
             }
-            this._thumbImage = value;
-            if (value && !value.isLoaded) {
-                value.onImageLoadedObservable.addOnce(function () { return _this._markAsDirty(); });
+            this._thumbBaseImage = value;
+            if (this.isVertical) {
+                if (value && !value.isLoaded) {
+                    value.onImageLoadedObservable.addOnce(function () {
+                        var rotatedValue = value._rotate90(-1);
+                        _this._thumbImage = rotatedValue;
+                        if (!rotatedValue.isLoaded) {
+                            rotatedValue.onImageLoadedObservable.addOnce(function () {
+                                _this._markAsDirty();
+                            });
+                        }
+                        _this._markAsDirty();
+                    });
+                }
+                this._thumbImage = value._rotate90(-1);
+                this._markAsDirty();
+            }
+            else {
+                this._thumbImage = value;
+                if (value && !value.isLoaded) {
+                    value.onImageLoadedObservable.addOnce(function () {
+                        _this._markAsDirty();
+                    });
+                }
+                this._markAsDirty();
             }
-            this._markAsDirty();
         },
         enumerable: true,
         configurable: true

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


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

@@ -1545,6 +1545,8 @@ declare module "babylonjs-gui/2D/controls/image" {
         autoScale: boolean;
         /** Gets or sets the streching mode used by the image */
         stretch: number;
+        /** @hidden */
+        _rotate90(n: number): Image;
         /**
          * Gets or sets the internal DOM image used to render the control
          */
@@ -2868,14 +2870,16 @@ declare module "babylonjs-gui/2D/controls/sliders/imageScrollBar" {
      */
     export class ImageScrollBar extends BaseSlider {
         name?: string | undefined;
+        private _backgroundBaseImage;
         private _backgroundImage;
         private _thumbImage;
+        private _thumbBaseImage;
         private _thumbLength;
         private _thumbHeight;
         private _barImageHeight;
         private _tempMeasure;
         /**
-         * Gets or sets the image used to render the background
+         * Gets or sets the image used to render the background for horizontal bar
          */
         backgroundImage: Image;
         /**
@@ -5528,6 +5532,8 @@ declare module BABYLON.GUI {
         autoScale: boolean;
         /** Gets or sets the streching mode used by the image */
         stretch: number;
+        /** @hidden */
+        _rotate90(n: number): Image;
         /**
          * Gets or sets the internal DOM image used to render the control
          */
@@ -6777,14 +6783,16 @@ declare module BABYLON.GUI {
      */
     export class ImageScrollBar extends BaseSlider {
         name?: string | undefined;
+        private _backgroundBaseImage;
         private _backgroundImage;
         private _thumbImage;
+        private _thumbBaseImage;
         private _thumbLength;
         private _thumbHeight;
         private _barImageHeight;
         private _tempMeasure;
         /**
-         * Gets or sets the image used to render the background
+         * Gets or sets the image used to render the background for horizontal bar
          */
         backgroundImage: Image;
         /**

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.js


+ 4 - 0
dist/preview release/nodeEditor/babylon.nodeEditor.max.js

@@ -52667,6 +52667,9 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _diagram_graphFrame__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../diagram/graphFrame */ "./diagram/graphFrame.ts");
 /* harmony import */ var _sharedComponents_textInputLineComponent__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../sharedComponents/textInputLineComponent */ "./sharedComponents/textInputLineComponent.tsx");
 /* harmony import */ var _sharedComponents_color3LineComponent__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../sharedComponents/color3LineComponent */ "./sharedComponents/color3LineComponent.tsx");
+/* harmony import */ var _sharedComponents_textLineComponent__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../sharedComponents/textLineComponent */ "./sharedComponents/textLineComponent.tsx");
+
+
 
 
 
@@ -52750,6 +52753,7 @@ var PropertyTabComponent = /** @class */ (function (_super) {
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { id: "title" }, "NODE MATERIAL EDITOR")),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", null,
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__["LineContainerComponent"], { title: "GENERAL" },
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_textLineComponent__WEBPACK_IMPORTED_MODULE_15__["TextLineComponent"], { label: "Version", value: babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_6__["Engine"].Version }),
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_sharedComponents_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: "Reset to default", onClick: function () {
                             _this.props.globalState.nodeMaterial.setToDefault();
                             _this.props.globalState.onResetRequiredObservable.notifyObservers();

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map


+ 1 - 1
dist/preview release/packagesSizeBaseLine.json

@@ -1 +1 @@
-{"thinEngineOnly":116435,"engineOnly":153253,"sceneOnly":498663,"minGridMaterial":628637,"minStandardMaterial":752569}
+{"thinEngineOnly":116435,"engineOnly":153253,"sceneOnly":498663,"minGridMaterial":628663,"minStandardMaterial":752595}

+ 224 - 41
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -519,6 +519,108 @@ _glTFExporter__WEBPACK_IMPORTED_MODULE_1__["_Exporter"].RegisterExtension(NAME,
 
 /***/ }),
 
+/***/ "./glTF/2.0/Extensions/KHR_materials_sheen.ts":
+/*!****************************************************!*\
+  !*** ./glTF/2.0/Extensions/KHR_materials_sheen.ts ***!
+  \****************************************************/
+/*! exports provided: KHR_materials_sheen */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return KHR_materials_sheen; });
+/* harmony import */ var _glTFExporter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFExporter */ "./glTF/2.0/glTFExporter.ts");
+/* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Maths/math");
+/* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__);
+
+
+var NAME = "KHR_materials_sheen";
+/**
+ * @hidden
+ */
+var KHR_materials_sheen = /** @class */ (function () {
+    function KHR_materials_sheen(exporter) {
+        /** Name of this extension */
+        this.name = NAME;
+        /** Defines whether this extension is enabled */
+        this.enabled = true;
+        /** Defines whether this extension is required */
+        this.required = false;
+        this._exportedTexture = null;
+        this._wasUsed = false;
+        this._exporter = exporter;
+    }
+    KHR_materials_sheen.prototype.dispose = function () {
+        delete this._exporter;
+    };
+    /** @hidden */
+    KHR_materials_sheen.prototype.onExporting = function () {
+        if (this._wasUsed) {
+            if (this._exporter._glTF.extensionsUsed == null) {
+                this._exporter._glTF.extensionsUsed = [];
+            }
+            if (this._exporter._glTF.extensionsUsed.indexOf(NAME) === -1) {
+                this._exporter._glTF.extensionsUsed.push(NAME);
+            }
+            if (this.required) {
+                if (this._exporter._glTF.extensionsRequired == null) {
+                    this._exporter._glTF.extensionsRequired = [];
+                }
+                if (this._exporter._glTF.extensionsRequired.indexOf(NAME) === -1) {
+                    this._exporter._glTF.extensionsRequired.push(NAME);
+                }
+            }
+            if (this._exporter._glTF.extensions == null) {
+                this._exporter._glTF.extensions = {};
+            }
+        }
+    };
+    KHR_materials_sheen.prototype.postExportTexture = function (context, textureInfo, babylonTexture) {
+        if (babylonTexture === this._exportedTexture || babylonTexture.reservedDataStore && babylonTexture.reservedDataStore.source === this._exportedTexture) {
+            this._textureInfo = textureInfo;
+        }
+    };
+    KHR_materials_sheen.prototype.postExportMaterialAdditionalTextures = function (context, node, babylonMaterial) {
+        if (babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__["PBRMaterial"]) {
+            if (babylonMaterial.sheen.isEnabled && babylonMaterial.sheen.texture) {
+                this._exportedTexture = babylonMaterial.sheen.texture;
+                return [babylonMaterial.sheen.texture];
+            }
+        }
+        return [];
+    };
+    KHR_materials_sheen.prototype.postExportMaterialAsync = function (context, node, babylonMaterial) {
+        var _this = this;
+        return new Promise(function (resolve, reject) {
+            if (babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__["PBRMaterial"]) {
+                if (!babylonMaterial.sheen.isEnabled) {
+                    resolve(node);
+                    return;
+                }
+                _this._wasUsed = true;
+                if (node.extensions == null) {
+                    node.extensions = {};
+                }
+                var sheenInfo = {
+                    colorFactor: babylonMaterial.sheen.color.asArray(),
+                    intensityFactor: babylonMaterial.sheen.intensity
+                };
+                if (_this._textureInfo) {
+                    sheenInfo.colorIntensityTexture = _this._textureInfo;
+                }
+                node.extensions[NAME] = sheenInfo;
+            }
+            resolve(node);
+        });
+    };
+    return KHR_materials_sheen;
+}());
+
+_glTFExporter__WEBPACK_IMPORTED_MODULE_0__["_Exporter"].RegisterExtension(NAME, function (exporter) { return new KHR_materials_sheen(exporter); });
+
+
+/***/ }),
+
 /***/ "./glTF/2.0/Extensions/KHR_texture_transform.ts":
 /*!******************************************************!*\
   !*** ./glTF/2.0/Extensions/KHR_texture_transform.ts ***!
@@ -543,6 +645,7 @@ var NAME = "KHR_texture_transform";
  */
 var KHR_texture_transform = /** @class */ (function () {
     function KHR_texture_transform(exporter) {
+        this._recordedTextures = [];
         /** Name of this extension */
         this.name = NAME;
         /** Defines whether this extension is enabled */
@@ -552,6 +655,10 @@ var KHR_texture_transform = /** @class */ (function () {
         this._exporter = exporter;
     }
     KHR_texture_transform.prototype.dispose = function () {
+        for (var _i = 0, _a = this._recordedTextures; _i < _a.length; _i++) {
+            var texture = _a[_i];
+            texture.dispose();
+        }
         delete this._exporter;
     };
     KHR_texture_transform.prototype.preExportTextureAsync = function (context, babylonTexture, mimeType) {
@@ -573,6 +680,9 @@ var KHR_texture_transform = /** @class */ (function () {
             if (babylonTexture.wAng !== 0) {
                 texture_transform_extension.rotation = babylonTexture.wAng;
             }
+            if (babylonTexture.coordinatesIndex !== 0) {
+                texture_transform_extension.texCoord = babylonTexture.coordinatesIndex;
+            }
             if (!Object.keys(texture_transform_extension).length) {
                 resolve(babylonTexture);
                 return;
@@ -595,12 +705,19 @@ var KHR_texture_transform = /** @class */ (function () {
      * @param scene
      */
     KHR_texture_transform.prototype._textureTransformTextureAsync = function (babylonTexture, scene) {
+        var _this = this;
         return new Promise(function (resolve) {
             var proceduralTexture = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__["ProceduralTexture"]("" + babylonTexture.name, babylonTexture.getSize(), "textureTransform", scene);
             if (!proceduralTexture) {
                 babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__["Tools"].Log("Cannot create procedural texture for " + babylonTexture.name + "!");
                 resolve(babylonTexture);
             }
+            proceduralTexture.reservedDataStore = {
+                hidden: true,
+                source: babylonTexture
+            };
+            _this._recordedTextures.push(proceduralTexture);
+            proceduralTexture.coordinatesIndex = babylonTexture.coordinatesIndex;
             proceduralTexture.setTexture("textureSampler", babylonTexture);
             proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
             // isReady trigger creation of effect if it doesnt exist yet
@@ -628,7 +745,7 @@ _glTFExporter__WEBPACK_IMPORTED_MODULE_1__["_Exporter"].RegisterExtension(NAME,
 /*!**************************************!*\
   !*** ./glTF/2.0/Extensions/index.ts ***!
   \**************************************/
-/*! exports provided: KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -639,6 +756,10 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _KHR_lights_punctual__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./KHR_lights_punctual */ "./glTF/2.0/Extensions/KHR_lights_punctual.ts");
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _KHR_lights_punctual__WEBPACK_IMPORTED_MODULE_1__["KHR_lights_punctual"]; });
 
+/* harmony import */ var _KHR_materials_sheen__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./KHR_materials_sheen */ "./glTF/2.0/Extensions/KHR_materials_sheen.ts");
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _KHR_materials_sheen__WEBPACK_IMPORTED_MODULE_2__["KHR_materials_sheen"]; });
+
+
 
 
 
@@ -1451,44 +1572,61 @@ var _Exporter = /** @class */ (function () {
         this._glTFMaterialExporter = new _glTFMaterialExporter__WEBPACK_IMPORTED_MODULE_2__["_GLTFMaterialExporter"](this);
         this._loadExtensions();
     }
-    _Exporter.prototype._applyExtensions = function (property, actionAsync) {
+    _Exporter.prototype._applyExtension = function (node, extensions, index, actionAsync) {
+        var _this = this;
+        if (index >= extensions.length) {
+            return Promise.resolve(node);
+        }
+        var currentPromise = actionAsync(extensions[index], node);
+        if (!currentPromise) {
+            return this._applyExtension(node, extensions, index + 1, actionAsync);
+        }
+        return currentPromise.then(function (newNode) { return _this._applyExtension(newNode || node, extensions, index + 1, actionAsync); });
+    };
+    _Exporter.prototype._applyExtensions = function (node, actionAsync) {
+        var extensions = [];
         for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
             var name_1 = _a[_i];
-            var extension = this._extensions[name_1];
-            if (extension.enabled) {
-                var exporterProperty = property;
-                exporterProperty._activeLoaderExtensions = exporterProperty._activeLoaderExtensions || {};
-                var activeLoaderExtensions = exporterProperty._activeLoaderExtensions;
-                if (!activeLoaderExtensions[name_1]) {
-                    activeLoaderExtensions[name_1] = true;
-                    try {
-                        var result = actionAsync(extension);
-                        if (result) {
-                            return result;
-                        }
-                    }
-                    finally {
-                        delete activeLoaderExtensions[name_1];
-                        delete exporterProperty._activeLoaderExtensions;
-                    }
-                }
-            }
+            extensions.push(this._extensions[name_1]);
         }
-        return null;
+        return this._applyExtension(node, extensions, 0, actionAsync);
     };
     _Exporter.prototype._extensionsPreExportTextureAsync = function (context, babylonTexture, mimeType) {
-        return this._applyExtensions(babylonTexture, function (extension) { return extension.preExportTextureAsync && extension.preExportTextureAsync(context, babylonTexture, mimeType); });
+        return this._applyExtensions(babylonTexture, function (extension, node) { return extension.preExportTextureAsync && extension.preExportTextureAsync(context, node, mimeType); });
     };
     _Exporter.prototype._extensionsPostExportMeshPrimitiveAsync = function (context, meshPrimitive, babylonSubMesh, binaryWriter) {
-        return this._applyExtensions(meshPrimitive, function (extension) { return extension.postExportMeshPrimitiveAsync && extension.postExportMeshPrimitiveAsync(context, meshPrimitive, babylonSubMesh, binaryWriter); });
+        return this._applyExtensions(meshPrimitive, function (extension, node) { return extension.postExportMeshPrimitiveAsync && extension.postExportMeshPrimitiveAsync(context, node, babylonSubMesh, binaryWriter); });
     };
     _Exporter.prototype._extensionsPostExportNodeAsync = function (context, node, babylonNode) {
-        return this._applyExtensions(node, function (extension) { return extension.postExportNodeAsync && extension.postExportNodeAsync(context, node, babylonNode); });
+        return this._applyExtensions(node, function (extension, node) { return extension.postExportNodeAsync && extension.postExportNodeAsync(context, node, babylonNode); });
     };
-    _Exporter.prototype._forEachExtensions = function (action) {
+    _Exporter.prototype._extensionsPostExportMaterialAsync = function (context, material, babylonMaterial) {
+        return this._applyExtensions(material, function (extension, node) { return extension.postExportMaterialAsync && extension.postExportMaterialAsync(context, node, babylonMaterial); });
+    };
+    _Exporter.prototype._extensionsPostExportMaterialAdditionalTextures = function (context, material, babylonMaterial) {
+        var output = [];
         for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
             var name_2 = _a[_i];
             var extension = this._extensions[name_2];
+            if (extension.postExportMaterialAdditionalTextures) {
+                output.push.apply(output, extension.postExportMaterialAdditionalTextures(context, material, babylonMaterial));
+            }
+        }
+        return output;
+    };
+    _Exporter.prototype._extensionsPostExportTextures = function (context, textureInfo, babylonTexture) {
+        for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
+            var name_3 = _a[_i];
+            var extension = this._extensions[name_3];
+            if (extension.postExportTexture) {
+                extension.postExportTexture(context, textureInfo, babylonTexture);
+            }
+        }
+    };
+    _Exporter.prototype._forEachExtensions = function (action) {
+        for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
+            var name_4 = _a[_i];
+            var extension = this._extensions[name_4];
             if (extension.enabled) {
                 action(extension);
             }
@@ -1502,9 +1640,15 @@ var _Exporter = /** @class */ (function () {
      */
     _Exporter.prototype._loadExtensions = function () {
         for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
-            var name_3 = _a[_i];
-            var extension = _Exporter._ExtensionFactories[name_3](this);
-            this._extensions[name_3] = extension;
+            var name_5 = _a[_i];
+            var extension = _Exporter._ExtensionFactories[name_5](this);
+            this._extensions[name_5] = extension;
+        }
+    };
+    _Exporter.prototype.dispose = function () {
+        for (var extensionKey in this._extensions) {
+            var extension = this._extensions[extensionKey];
+            extension.dispose();
         }
     };
     /**
@@ -2003,10 +2147,12 @@ var _Exporter = /** @class */ (function () {
     /**
      * Generates data for .gltf and .bin files based on the glTF prefix string
      * @param glTFPrefix Text to use when prefixing a glTF file
+     * @param dispose Dispose the exporter
      * @returns GLTFData with glTF file data
      */
-    _Exporter.prototype._generateGLTFAsync = function (glTFPrefix) {
+    _Exporter.prototype._generateGLTFAsync = function (glTFPrefix, dispose) {
         var _this = this;
+        if (dispose === void 0) { dispose = true; }
         return this._generateBinaryAsync().then(function (binaryBuffer) {
             _this._extensionsOnExporting();
             var jsonText = _this.generateJSON(false, glTFPrefix, true);
@@ -2021,6 +2167,9 @@ var _Exporter = /** @class */ (function () {
                     container.glTFFiles[image] = new Blob([_this._imageData[image].data], { type: _this._imageData[image].mimeType });
                 }
             }
+            if (dispose) {
+                _this.dispose();
+            }
             return container;
         });
     };
@@ -2049,13 +2198,11 @@ var _Exporter = /** @class */ (function () {
         return padding;
     };
     /**
-     * Generates a glb file from the json and binary data
-     * Returns an object with the glb file name as the key and data as the value
-     * @param glTFPrefix
-     * @returns object with glb filename as key and data as value
+     * @hidden
      */
-    _Exporter.prototype._generateGLBAsync = function (glTFPrefix) {
+    _Exporter.prototype._generateGLBAsync = function (glTFPrefix, dispose) {
         var _this = this;
+        if (dispose === void 0) { dispose = true; }
         return this._generateBinaryAsync().then(function (binaryBuffer) {
             _this._extensionsOnExporting();
             var jsonText = _this.generateJSON(true);
@@ -2121,6 +2268,9 @@ var _Exporter = /** @class */ (function () {
             if (_this._localEngine != null) {
                 _this._localEngine.dispose();
             }
+            if (dispose) {
+                _this.dispose();
+            }
             return container;
         });
     };
@@ -2530,6 +2680,9 @@ var _Exporter = /** @class */ (function () {
                         }
                         else {
                             return promise.then(function (node) {
+                                if (!node) {
+                                    return;
+                                }
                                 _this._nodes.push(node);
                                 nodeIndex = _this._nodes.length - 1;
                                 nodeMap[babylonNode.uniqueId] = nodeIndex;
@@ -3069,7 +3222,31 @@ var _GLTFMaterialExporter = /** @class */ (function () {
         _GLTFMaterialExporter._SetAlphaMode(glTFMaterial, babylonStandardMaterial);
         materials.push(glTFMaterial);
         materialMap[babylonStandardMaterial.uniqueId] = materials.length - 1;
-        return Promise.all(promises).then(function () { });
+        return this._finishMaterial(promises, glTFMaterial, babylonStandardMaterial, mimeType);
+    };
+    _GLTFMaterialExporter.prototype._finishMaterial = function (promises, glTFMaterial, babylonMaterial, mimeType) {
+        var _this = this;
+        return Promise.all(promises).then(function () {
+            var textures = _this._exporter._extensionsPostExportMaterialAdditionalTextures("exportMaterial", glTFMaterial, babylonMaterial);
+            var tasks = null;
+            for (var _i = 0, textures_1 = textures; _i < textures_1.length; _i++) {
+                var texture = textures_1[_i];
+                if (!tasks) {
+                    tasks = [];
+                }
+                tasks.push(_this._exportTextureAsync(texture, mimeType));
+            }
+            if (!tasks) {
+                tasks = [Promise.resolve(null)];
+            }
+            return Promise.all(tasks).then(function () {
+                var extensionWork = _this._exporter._extensionsPostExportMaterialAsync("exportMaterial", glTFMaterial, babylonMaterial);
+                if (!extensionWork) {
+                    return glTFMaterial;
+                }
+                return extensionWork.then(function () { return glTFMaterial; });
+            });
+        });
     };
     /**
      * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
@@ -3149,7 +3326,7 @@ var _GLTFMaterialExporter = /** @class */ (function () {
         glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
         materials.push(glTFMaterial);
         materialMap[babylonPBRMetalRoughMaterial.uniqueId] = materials.length - 1;
-        return Promise.all(promises).then(function () { });
+        return this._finishMaterial(promises, glTFMaterial, babylonPBRMetalRoughMaterial, mimeType);
     };
     /**
      * Converts an image typed array buffer to a base64 image
@@ -3710,7 +3887,8 @@ var _GLTFMaterialExporter = /** @class */ (function () {
                     var promise = this._exportTextureAsync(babylonPBRMaterial.ambientTexture, mimeType).then(function (glTFTexture) {
                         if (glTFTexture) {
                             var occlusionTexture = {
-                                index: glTFTexture.index
+                                index: glTFTexture.index,
+                                texCoord: glTFTexture.texCoord
                             };
                             glTFMaterial.occlusionTexture = occlusionTexture;
                             if (babylonPBRMaterial.ambientTextureStrength) {
@@ -3736,7 +3914,7 @@ var _GLTFMaterialExporter = /** @class */ (function () {
             materials.push(glTFMaterial);
             materialMap[babylonPBRMaterial.uniqueId] = materials.length - 1;
         }
-        return Promise.all(promises).then(function (result) { });
+        return this._finishMaterial(promises, glTFMaterial, babylonPBRMaterial, mimeType);
     };
     _GLTFMaterialExporter.prototype.getPixelsFromTexture = function (babylonTexture) {
         var pixels = babylonTexture.textureType === babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Constants"].TEXTURETYPE_UNSIGNED_INT ? babylonTexture.readPixels() : babylonTexture.readPixels();
@@ -3795,6 +3973,7 @@ var _GLTFMaterialExporter = /** @class */ (function () {
                     var textureInfo = _this._getTextureInfoFromBase64(base64Data, babylonTexture.name.replace(/\.\/|\/|\.\\|\\/g, "_"), mimeType, babylonTexture.coordinatesIndex, samplerIndex_1);
                     if (textureInfo) {
                         _this._textureMap[textureUid] = textureInfo;
+                        _this._exporter._extensionsPostExportTextures("linkTextureInfo", textureInfo, babylonTexture);
                     }
                     return textureInfo;
                 });
@@ -4162,7 +4341,7 @@ var _GLTFUtilities = /** @class */ (function () {
 /*!***************************!*\
   !*** ./glTF/2.0/index.ts ***!
   \***************************/
-/*! exports provided: GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -4195,6 +4374,8 @@ __webpack_require__.r(__webpack_exports__);
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _Extensions__WEBPACK_IMPORTED_MODULE_7__["KHR_lights_punctual"]; });
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _Extensions__WEBPACK_IMPORTED_MODULE_7__["KHR_materials_sheen"]; });
+
 
 
 
@@ -4249,7 +4430,7 @@ var __IGLTFExporterExtension = 0; // I am here to allow dts to be created
 /*!******************************************!*\
   !*** ./legacy/legacy-glTF2Serializer.ts ***!
   \******************************************/
-/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -4281,6 +4462,8 @@ __webpack_require__.r(__webpack_exports__);
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _glTF_2_0__WEBPACK_IMPORTED_MODULE_4__["KHR_lights_punctual"]; });
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _glTF_2_0__WEBPACK_IMPORTED_MODULE_4__["KHR_materials_sheen"]; });
+
 
 
 

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.js.map


Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/serializers/babylon.glTF2Serializer.min.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/serializers/babylon.objSerializer.min.js


+ 70 - 19
dist/preview release/serializers/babylonjs.serializers.d.ts

@@ -53,11 +53,18 @@ declare module BABYLON.GLTF2.Exporter {
         /**
          * Define this method to modify the default behavior before exporting a texture
          * @param context The context when loading the asset
-         * @param babylonTexture The glTF texture info property
+         * @param babylonTexture The Babylon.js texture
          * @param mimeType The mime-type of the generated image
-         * @returns A promise that resolves with the exported glTF texture info when the export is complete, or null if not handled
+         * @returns A promise that resolves with the exported texture
          */
-        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
+        /**
+         * Define this method to get notified when a texture info is created
+         * @param context The context when loading the asset
+         * @param textureInfo The glTF texture info
+         * @param babylonTexture The Babylon.js texture
+         */
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         /**
          * Define this method to modify the default behavior when exporting texture info
          * @param context The context when loading the asset
@@ -66,7 +73,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param binaryWriter glTF serializer binary writer instance
          * @returns nullable IMeshPrimitive promise
          */
-        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<IMeshPrimitive>;
         /**
          * Define this method to modify the default behavior when exporting a node
          * @param context The context when exporting the node
@@ -74,7 +81,21 @@ declare module BABYLON.GLTF2.Exporter {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Promise<INode>;
+        /**
+         * Define this method to modify the default behavior when exporting a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns nullable IMaterial promise
+         */
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
+        /**
+         * Defint this method to return additional textures to export from a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns List of textures
+         */
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
         /**
          * Called after the exporter state changes to EXPORTING
          */
@@ -168,7 +189,8 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
+        private _finishMaterial;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
@@ -179,7 +201,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         /**
          * Converts an image typed array buffer to a base64 image
          * @param buffer typed array buffer
@@ -278,7 +300,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         private setMetallicRoughnessPbrMaterial;
         private getPixelsFromTexture;
         /**
@@ -560,10 +582,14 @@ declare module BABYLON.GLTF2.Exporter {
         private _extensions;
         private static _ExtensionNames;
         private static _ExtensionFactories;
+        private _applyExtension;
         private _applyExtensions;
-        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>>;
-        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
-        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Nullable<BaseTexture>>;
+        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<Nullable<IMeshPrimitive>>;
+        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<Nullable<INode>>;
+        _extensionsPostExportMaterialAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<Nullable<IMaterial>>;
+        _extensionsPostExportMaterialAdditionalTextures(context: string, material: IMaterial, babylonMaterial: Material): BaseTexture[];
+        _extensionsPostExportTextures(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         private _forEachExtensions;
         private _extensionsOnExporting;
         /**
@@ -576,6 +602,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param options Options to modify the behavior of the exporter
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
+        dispose(): void;
         /**
          * Registers a glTF exporter extension
          * @param name Name of the extension to export
@@ -670,9 +697,10 @@ declare module BABYLON.GLTF2.Exporter {
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix Text to use when prefixing a glTF file
+         * @param dispose Dispose the exporter
          * @returns GLTFData with glTF file data
          */
-        _generateGLTFAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLTFAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Creates a binary buffer for glTF
          * @returns array buffer for binary data
@@ -685,12 +713,9 @@ declare module BABYLON.GLTF2.Exporter {
          */
         private _getPadding;
         /**
-         * Generates a glb file from the json and binary data
-         * Returns an object with the glb file name as the key and data as the value
-         * @param glTFPrefix
-         * @returns object with glb filename as key and data as value
+         * @hidden
          */
-        _generateGLBAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLBAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Sets the TRS for each node
          * @param node glTF Node for storing the transformation data
@@ -1006,6 +1031,7 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
      * @hidden
      */
     export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
+        private _recordedTextures;
         /** Name of this extension */
         readonly name: string;
         /** Defines whether this extension is enabled */
@@ -1016,7 +1042,7 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
         private _exporter;
         constructor(exporter: _Exporter);
         dispose(): void;
-        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
         /**
          * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
          * @param babylonTexture
@@ -1055,7 +1081,32 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<INode>;
+    }
+}
+declare module BABYLON.GLTF2.Exporter.Extensions {
+    /**
+     * @hidden
+     */
+    export class KHR_materials_sheen implements IGLTFExporterExtensionV2 {
+        /** Name of this extension */
+        readonly name: string;
+        /** Defines whether this extension is enabled */
+        enabled: boolean;
+        /** Defines whether this extension is required */
+        required: boolean;
+        /** Reference to the glTF exporter */
+        private _exporter;
+        private _textureInfo;
+        private _exportedTexture;
+        private _wasUsed;
+        constructor(exporter: _Exporter);
+        dispose(): void;
+        /** @hidden */
+        onExporting(): void;
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void;
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
     }
 }
 declare module BABYLON {

+ 233 - 44
dist/preview release/serializers/babylonjs.serializers.js

@@ -697,6 +697,108 @@ _glTFExporter__WEBPACK_IMPORTED_MODULE_1__["_Exporter"].RegisterExtension(NAME,
 
 /***/ }),
 
+/***/ "./glTF/2.0/Extensions/KHR_materials_sheen.ts":
+/*!****************************************************!*\
+  !*** ./glTF/2.0/Extensions/KHR_materials_sheen.ts ***!
+  \****************************************************/
+/*! exports provided: KHR_materials_sheen */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return KHR_materials_sheen; });
+/* harmony import */ var _glTFExporter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFExporter */ "./glTF/2.0/glTFExporter.ts");
+/* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Maths/math");
+/* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__);
+
+
+var NAME = "KHR_materials_sheen";
+/**
+ * @hidden
+ */
+var KHR_materials_sheen = /** @class */ (function () {
+    function KHR_materials_sheen(exporter) {
+        /** Name of this extension */
+        this.name = NAME;
+        /** Defines whether this extension is enabled */
+        this.enabled = true;
+        /** Defines whether this extension is required */
+        this.required = false;
+        this._exportedTexture = null;
+        this._wasUsed = false;
+        this._exporter = exporter;
+    }
+    KHR_materials_sheen.prototype.dispose = function () {
+        delete this._exporter;
+    };
+    /** @hidden */
+    KHR_materials_sheen.prototype.onExporting = function () {
+        if (this._wasUsed) {
+            if (this._exporter._glTF.extensionsUsed == null) {
+                this._exporter._glTF.extensionsUsed = [];
+            }
+            if (this._exporter._glTF.extensionsUsed.indexOf(NAME) === -1) {
+                this._exporter._glTF.extensionsUsed.push(NAME);
+            }
+            if (this.required) {
+                if (this._exporter._glTF.extensionsRequired == null) {
+                    this._exporter._glTF.extensionsRequired = [];
+                }
+                if (this._exporter._glTF.extensionsRequired.indexOf(NAME) === -1) {
+                    this._exporter._glTF.extensionsRequired.push(NAME);
+                }
+            }
+            if (this._exporter._glTF.extensions == null) {
+                this._exporter._glTF.extensions = {};
+            }
+        }
+    };
+    KHR_materials_sheen.prototype.postExportTexture = function (context, textureInfo, babylonTexture) {
+        if (babylonTexture === this._exportedTexture || babylonTexture.reservedDataStore && babylonTexture.reservedDataStore.source === this._exportedTexture) {
+            this._textureInfo = textureInfo;
+        }
+    };
+    KHR_materials_sheen.prototype.postExportMaterialAdditionalTextures = function (context, node, babylonMaterial) {
+        if (babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__["PBRMaterial"]) {
+            if (babylonMaterial.sheen.isEnabled && babylonMaterial.sheen.texture) {
+                this._exportedTexture = babylonMaterial.sheen.texture;
+                return [babylonMaterial.sheen.texture];
+            }
+        }
+        return [];
+    };
+    KHR_materials_sheen.prototype.postExportMaterialAsync = function (context, node, babylonMaterial) {
+        var _this = this;
+        return new Promise(function (resolve, reject) {
+            if (babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_1__["PBRMaterial"]) {
+                if (!babylonMaterial.sheen.isEnabled) {
+                    resolve(node);
+                    return;
+                }
+                _this._wasUsed = true;
+                if (node.extensions == null) {
+                    node.extensions = {};
+                }
+                var sheenInfo = {
+                    colorFactor: babylonMaterial.sheen.color.asArray(),
+                    intensityFactor: babylonMaterial.sheen.intensity
+                };
+                if (_this._textureInfo) {
+                    sheenInfo.colorIntensityTexture = _this._textureInfo;
+                }
+                node.extensions[NAME] = sheenInfo;
+            }
+            resolve(node);
+        });
+    };
+    return KHR_materials_sheen;
+}());
+
+_glTFExporter__WEBPACK_IMPORTED_MODULE_0__["_Exporter"].RegisterExtension(NAME, function (exporter) { return new KHR_materials_sheen(exporter); });
+
+
+/***/ }),
+
 /***/ "./glTF/2.0/Extensions/KHR_texture_transform.ts":
 /*!******************************************************!*\
   !*** ./glTF/2.0/Extensions/KHR_texture_transform.ts ***!
@@ -721,6 +823,7 @@ var NAME = "KHR_texture_transform";
  */
 var KHR_texture_transform = /** @class */ (function () {
     function KHR_texture_transform(exporter) {
+        this._recordedTextures = [];
         /** Name of this extension */
         this.name = NAME;
         /** Defines whether this extension is enabled */
@@ -730,6 +833,10 @@ var KHR_texture_transform = /** @class */ (function () {
         this._exporter = exporter;
     }
     KHR_texture_transform.prototype.dispose = function () {
+        for (var _i = 0, _a = this._recordedTextures; _i < _a.length; _i++) {
+            var texture = _a[_i];
+            texture.dispose();
+        }
         delete this._exporter;
     };
     KHR_texture_transform.prototype.preExportTextureAsync = function (context, babylonTexture, mimeType) {
@@ -751,6 +858,9 @@ var KHR_texture_transform = /** @class */ (function () {
             if (babylonTexture.wAng !== 0) {
                 texture_transform_extension.rotation = babylonTexture.wAng;
             }
+            if (babylonTexture.coordinatesIndex !== 0) {
+                texture_transform_extension.texCoord = babylonTexture.coordinatesIndex;
+            }
             if (!Object.keys(texture_transform_extension).length) {
                 resolve(babylonTexture);
                 return;
@@ -773,12 +883,19 @@ var KHR_texture_transform = /** @class */ (function () {
      * @param scene
      */
     KHR_texture_transform.prototype._textureTransformTextureAsync = function (babylonTexture, scene) {
+        var _this = this;
         return new Promise(function (resolve) {
             var proceduralTexture = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__["ProceduralTexture"]("" + babylonTexture.name, babylonTexture.getSize(), "textureTransform", scene);
             if (!proceduralTexture) {
                 babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__["Tools"].Log("Cannot create procedural texture for " + babylonTexture.name + "!");
                 resolve(babylonTexture);
             }
+            proceduralTexture.reservedDataStore = {
+                hidden: true,
+                source: babylonTexture
+            };
+            _this._recordedTextures.push(proceduralTexture);
+            proceduralTexture.coordinatesIndex = babylonTexture.coordinatesIndex;
             proceduralTexture.setTexture("textureSampler", babylonTexture);
             proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
             // isReady trigger creation of effect if it doesnt exist yet
@@ -806,7 +923,7 @@ _glTFExporter__WEBPACK_IMPORTED_MODULE_1__["_Exporter"].RegisterExtension(NAME,
 /*!**************************************!*\
   !*** ./glTF/2.0/Extensions/index.ts ***!
   \**************************************/
-/*! exports provided: KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -817,6 +934,10 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _KHR_lights_punctual__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./KHR_lights_punctual */ "./glTF/2.0/Extensions/KHR_lights_punctual.ts");
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _KHR_lights_punctual__WEBPACK_IMPORTED_MODULE_1__["KHR_lights_punctual"]; });
 
+/* harmony import */ var _KHR_materials_sheen__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./KHR_materials_sheen */ "./glTF/2.0/Extensions/KHR_materials_sheen.ts");
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _KHR_materials_sheen__WEBPACK_IMPORTED_MODULE_2__["KHR_materials_sheen"]; });
+
+
 
 
 
@@ -1629,44 +1750,61 @@ var _Exporter = /** @class */ (function () {
         this._glTFMaterialExporter = new _glTFMaterialExporter__WEBPACK_IMPORTED_MODULE_2__["_GLTFMaterialExporter"](this);
         this._loadExtensions();
     }
-    _Exporter.prototype._applyExtensions = function (property, actionAsync) {
+    _Exporter.prototype._applyExtension = function (node, extensions, index, actionAsync) {
+        var _this = this;
+        if (index >= extensions.length) {
+            return Promise.resolve(node);
+        }
+        var currentPromise = actionAsync(extensions[index], node);
+        if (!currentPromise) {
+            return this._applyExtension(node, extensions, index + 1, actionAsync);
+        }
+        return currentPromise.then(function (newNode) { return _this._applyExtension(newNode || node, extensions, index + 1, actionAsync); });
+    };
+    _Exporter.prototype._applyExtensions = function (node, actionAsync) {
+        var extensions = [];
         for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
             var name_1 = _a[_i];
-            var extension = this._extensions[name_1];
-            if (extension.enabled) {
-                var exporterProperty = property;
-                exporterProperty._activeLoaderExtensions = exporterProperty._activeLoaderExtensions || {};
-                var activeLoaderExtensions = exporterProperty._activeLoaderExtensions;
-                if (!activeLoaderExtensions[name_1]) {
-                    activeLoaderExtensions[name_1] = true;
-                    try {
-                        var result = actionAsync(extension);
-                        if (result) {
-                            return result;
-                        }
-                    }
-                    finally {
-                        delete activeLoaderExtensions[name_1];
-                        delete exporterProperty._activeLoaderExtensions;
-                    }
-                }
-            }
+            extensions.push(this._extensions[name_1]);
         }
-        return null;
+        return this._applyExtension(node, extensions, 0, actionAsync);
     };
     _Exporter.prototype._extensionsPreExportTextureAsync = function (context, babylonTexture, mimeType) {
-        return this._applyExtensions(babylonTexture, function (extension) { return extension.preExportTextureAsync && extension.preExportTextureAsync(context, babylonTexture, mimeType); });
+        return this._applyExtensions(babylonTexture, function (extension, node) { return extension.preExportTextureAsync && extension.preExportTextureAsync(context, node, mimeType); });
     };
     _Exporter.prototype._extensionsPostExportMeshPrimitiveAsync = function (context, meshPrimitive, babylonSubMesh, binaryWriter) {
-        return this._applyExtensions(meshPrimitive, function (extension) { return extension.postExportMeshPrimitiveAsync && extension.postExportMeshPrimitiveAsync(context, meshPrimitive, babylonSubMesh, binaryWriter); });
+        return this._applyExtensions(meshPrimitive, function (extension, node) { return extension.postExportMeshPrimitiveAsync && extension.postExportMeshPrimitiveAsync(context, node, babylonSubMesh, binaryWriter); });
     };
     _Exporter.prototype._extensionsPostExportNodeAsync = function (context, node, babylonNode) {
-        return this._applyExtensions(node, function (extension) { return extension.postExportNodeAsync && extension.postExportNodeAsync(context, node, babylonNode); });
+        return this._applyExtensions(node, function (extension, node) { return extension.postExportNodeAsync && extension.postExportNodeAsync(context, node, babylonNode); });
     };
-    _Exporter.prototype._forEachExtensions = function (action) {
+    _Exporter.prototype._extensionsPostExportMaterialAsync = function (context, material, babylonMaterial) {
+        return this._applyExtensions(material, function (extension, node) { return extension.postExportMaterialAsync && extension.postExportMaterialAsync(context, node, babylonMaterial); });
+    };
+    _Exporter.prototype._extensionsPostExportMaterialAdditionalTextures = function (context, material, babylonMaterial) {
+        var output = [];
         for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
             var name_2 = _a[_i];
             var extension = this._extensions[name_2];
+            if (extension.postExportMaterialAdditionalTextures) {
+                output.push.apply(output, extension.postExportMaterialAdditionalTextures(context, material, babylonMaterial));
+            }
+        }
+        return output;
+    };
+    _Exporter.prototype._extensionsPostExportTextures = function (context, textureInfo, babylonTexture) {
+        for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
+            var name_3 = _a[_i];
+            var extension = this._extensions[name_3];
+            if (extension.postExportTexture) {
+                extension.postExportTexture(context, textureInfo, babylonTexture);
+            }
+        }
+    };
+    _Exporter.prototype._forEachExtensions = function (action) {
+        for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
+            var name_4 = _a[_i];
+            var extension = this._extensions[name_4];
             if (extension.enabled) {
                 action(extension);
             }
@@ -1680,9 +1818,15 @@ var _Exporter = /** @class */ (function () {
      */
     _Exporter.prototype._loadExtensions = function () {
         for (var _i = 0, _a = _Exporter._ExtensionNames; _i < _a.length; _i++) {
-            var name_3 = _a[_i];
-            var extension = _Exporter._ExtensionFactories[name_3](this);
-            this._extensions[name_3] = extension;
+            var name_5 = _a[_i];
+            var extension = _Exporter._ExtensionFactories[name_5](this);
+            this._extensions[name_5] = extension;
+        }
+    };
+    _Exporter.prototype.dispose = function () {
+        for (var extensionKey in this._extensions) {
+            var extension = this._extensions[extensionKey];
+            extension.dispose();
         }
     };
     /**
@@ -2181,10 +2325,12 @@ var _Exporter = /** @class */ (function () {
     /**
      * Generates data for .gltf and .bin files based on the glTF prefix string
      * @param glTFPrefix Text to use when prefixing a glTF file
+     * @param dispose Dispose the exporter
      * @returns GLTFData with glTF file data
      */
-    _Exporter.prototype._generateGLTFAsync = function (glTFPrefix) {
+    _Exporter.prototype._generateGLTFAsync = function (glTFPrefix, dispose) {
         var _this = this;
+        if (dispose === void 0) { dispose = true; }
         return this._generateBinaryAsync().then(function (binaryBuffer) {
             _this._extensionsOnExporting();
             var jsonText = _this.generateJSON(false, glTFPrefix, true);
@@ -2199,6 +2345,9 @@ var _Exporter = /** @class */ (function () {
                     container.glTFFiles[image] = new Blob([_this._imageData[image].data], { type: _this._imageData[image].mimeType });
                 }
             }
+            if (dispose) {
+                _this.dispose();
+            }
             return container;
         });
     };
@@ -2227,13 +2376,11 @@ var _Exporter = /** @class */ (function () {
         return padding;
     };
     /**
-     * Generates a glb file from the json and binary data
-     * Returns an object with the glb file name as the key and data as the value
-     * @param glTFPrefix
-     * @returns object with glb filename as key and data as value
+     * @hidden
      */
-    _Exporter.prototype._generateGLBAsync = function (glTFPrefix) {
+    _Exporter.prototype._generateGLBAsync = function (glTFPrefix, dispose) {
         var _this = this;
+        if (dispose === void 0) { dispose = true; }
         return this._generateBinaryAsync().then(function (binaryBuffer) {
             _this._extensionsOnExporting();
             var jsonText = _this.generateJSON(true);
@@ -2299,6 +2446,9 @@ var _Exporter = /** @class */ (function () {
             if (_this._localEngine != null) {
                 _this._localEngine.dispose();
             }
+            if (dispose) {
+                _this.dispose();
+            }
             return container;
         });
     };
@@ -2708,6 +2858,9 @@ var _Exporter = /** @class */ (function () {
                         }
                         else {
                             return promise.then(function (node) {
+                                if (!node) {
+                                    return;
+                                }
                                 _this._nodes.push(node);
                                 nodeIndex = _this._nodes.length - 1;
                                 nodeMap[babylonNode.uniqueId] = nodeIndex;
@@ -3247,7 +3400,31 @@ var _GLTFMaterialExporter = /** @class */ (function () {
         _GLTFMaterialExporter._SetAlphaMode(glTFMaterial, babylonStandardMaterial);
         materials.push(glTFMaterial);
         materialMap[babylonStandardMaterial.uniqueId] = materials.length - 1;
-        return Promise.all(promises).then(function () { });
+        return this._finishMaterial(promises, glTFMaterial, babylonStandardMaterial, mimeType);
+    };
+    _GLTFMaterialExporter.prototype._finishMaterial = function (promises, glTFMaterial, babylonMaterial, mimeType) {
+        var _this = this;
+        return Promise.all(promises).then(function () {
+            var textures = _this._exporter._extensionsPostExportMaterialAdditionalTextures("exportMaterial", glTFMaterial, babylonMaterial);
+            var tasks = null;
+            for (var _i = 0, textures_1 = textures; _i < textures_1.length; _i++) {
+                var texture = textures_1[_i];
+                if (!tasks) {
+                    tasks = [];
+                }
+                tasks.push(_this._exportTextureAsync(texture, mimeType));
+            }
+            if (!tasks) {
+                tasks = [Promise.resolve(null)];
+            }
+            return Promise.all(tasks).then(function () {
+                var extensionWork = _this._exporter._extensionsPostExportMaterialAsync("exportMaterial", glTFMaterial, babylonMaterial);
+                if (!extensionWork) {
+                    return glTFMaterial;
+                }
+                return extensionWork.then(function () { return glTFMaterial; });
+            });
+        });
     };
     /**
      * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
@@ -3327,7 +3504,7 @@ var _GLTFMaterialExporter = /** @class */ (function () {
         glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
         materials.push(glTFMaterial);
         materialMap[babylonPBRMetalRoughMaterial.uniqueId] = materials.length - 1;
-        return Promise.all(promises).then(function () { });
+        return this._finishMaterial(promises, glTFMaterial, babylonPBRMetalRoughMaterial, mimeType);
     };
     /**
      * Converts an image typed array buffer to a base64 image
@@ -3888,7 +4065,8 @@ var _GLTFMaterialExporter = /** @class */ (function () {
                     var promise = this._exportTextureAsync(babylonPBRMaterial.ambientTexture, mimeType).then(function (glTFTexture) {
                         if (glTFTexture) {
                             var occlusionTexture = {
-                                index: glTFTexture.index
+                                index: glTFTexture.index,
+                                texCoord: glTFTexture.texCoord
                             };
                             glTFMaterial.occlusionTexture = occlusionTexture;
                             if (babylonPBRMaterial.ambientTextureStrength) {
@@ -3914,7 +4092,7 @@ var _GLTFMaterialExporter = /** @class */ (function () {
             materials.push(glTFMaterial);
             materialMap[babylonPBRMaterial.uniqueId] = materials.length - 1;
         }
-        return Promise.all(promises).then(function (result) { });
+        return this._finishMaterial(promises, glTFMaterial, babylonPBRMaterial, mimeType);
     };
     _GLTFMaterialExporter.prototype.getPixelsFromTexture = function (babylonTexture) {
         var pixels = babylonTexture.textureType === babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Constants"].TEXTURETYPE_UNSIGNED_INT ? babylonTexture.readPixels() : babylonTexture.readPixels();
@@ -3973,6 +4151,7 @@ var _GLTFMaterialExporter = /** @class */ (function () {
                     var textureInfo = _this._getTextureInfoFromBase64(base64Data, babylonTexture.name.replace(/\.\/|\/|\.\\|\\/g, "_"), mimeType, babylonTexture.coordinatesIndex, samplerIndex_1);
                     if (textureInfo) {
                         _this._textureMap[textureUid] = textureInfo;
+                        _this._exporter._extensionsPostExportTextures("linkTextureInfo", textureInfo, babylonTexture);
                     }
                     return textureInfo;
                 });
@@ -4340,7 +4519,7 @@ var _GLTFUtilities = /** @class */ (function () {
 /*!***************************!*\
   !*** ./glTF/2.0/index.ts ***!
   \***************************/
-/*! exports provided: GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -4373,6 +4552,8 @@ __webpack_require__.r(__webpack_exports__);
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _Extensions__WEBPACK_IMPORTED_MODULE_7__["KHR_lights_punctual"]; });
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _Extensions__WEBPACK_IMPORTED_MODULE_7__["KHR_materials_sheen"]; });
+
 
 
 
@@ -4427,7 +4608,7 @@ var __IGLTFExporterExtension = 0; // I am here to allow dts to be created
 /*!***********************!*\
   !*** ./glTF/index.ts ***!
   \***********************/
-/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -4456,6 +4637,8 @@ __webpack_require__.r(__webpack_exports__);
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _2_0__WEBPACK_IMPORTED_MODULE_1__["KHR_lights_punctual"]; });
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _2_0__WEBPACK_IMPORTED_MODULE_1__["KHR_materials_sheen"]; });
+
 
 
 
@@ -4466,7 +4649,7 @@ __webpack_require__.r(__webpack_exports__);
 /*!******************!*\
   !*** ./index.ts ***!
   \******************/
-/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, OBJExport, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, STLExport, KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, OBJExport, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, STLExport, KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -4497,6 +4680,8 @@ __webpack_require__.r(__webpack_exports__);
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _glTF__WEBPACK_IMPORTED_MODULE_1__["KHR_lights_punctual"]; });
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _glTF__WEBPACK_IMPORTED_MODULE_1__["KHR_materials_sheen"]; });
+
 /* harmony import */ var _stl__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stl */ "./stl/index.ts");
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "STLExport", function() { return _stl__WEBPACK_IMPORTED_MODULE_2__["STLExport"]; });
 
@@ -4511,7 +4696,7 @@ __webpack_require__.r(__webpack_exports__);
 /*!******************************************!*\
   !*** ./legacy/legacy-glTF2Serializer.ts ***!
   \******************************************/
-/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -4543,6 +4728,8 @@ __webpack_require__.r(__webpack_exports__);
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _glTF_2_0__WEBPACK_IMPORTED_MODULE_4__["KHR_lights_punctual"]; });
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _glTF_2_0__WEBPACK_IMPORTED_MODULE_4__["KHR_materials_sheen"]; });
+
 
 
 
@@ -4653,7 +4840,7 @@ if (typeof globalObject !== "undefined") {
 /*!**************************!*\
   !*** ./legacy/legacy.ts ***!
   \**************************/
-/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, OBJExport, STLExport, KHR_texture_transform, KHR_lights_punctual */
+/*! exports provided: __IGLTFExporterExtension, GLTFData, GLTF2Export, _GLTFAnimation, _Exporter, _BinaryWriter, __IGLTFExporterExtensionV2, _GLTFMaterialExporter, _GLTFUtilities, OBJExport, STLExport, KHR_texture_transform, KHR_lights_punctual, KHR_materials_sheen */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 "use strict";
@@ -4682,6 +4869,8 @@ __webpack_require__.r(__webpack_exports__);
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_lights_punctual", function() { return _legacy_glTF2Serializer__WEBPACK_IMPORTED_MODULE_1__["KHR_lights_punctual"]; });
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "KHR_materials_sheen", function() { return _legacy_glTF2Serializer__WEBPACK_IMPORTED_MODULE_1__["KHR_materials_sheen"]; });
+
 /* harmony import */ var _legacy_objSerializer__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./legacy-objSerializer */ "./legacy/legacy-objSerializer.ts");
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "OBJExport", function() { return _legacy_objSerializer__WEBPACK_IMPORTED_MODULE_2__["OBJExport"]; });
 

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.js.map


Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/serializers/babylonjs.serializers.min.js


+ 152 - 43
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -47,14 +47,15 @@ declare module "babylonjs-serializers/glTF/glTFFileExporter" {
     }
 }
 declare module "babylonjs-serializers/glTF/2.0/glTFExporterExtension" {
-    import { ImageMimeType, IMeshPrimitive, INode } from "babylonjs-gltf2interface";
+    import { ImageMimeType, IMeshPrimitive, INode, IMaterial, ITextureInfo } from "babylonjs-gltf2interface";
     import { Node } from "babylonjs/node";
-    import { Nullable } from "babylonjs/types";
     import { Texture } from "babylonjs/Materials/Textures/texture";
     import { SubMesh } from "babylonjs/Meshes/subMesh";
     import { IDisposable } from "babylonjs/scene";
     import { _BinaryWriter } from "babylonjs-serializers/glTF/2.0/glTFExporter";
     import { IGLTFExporterExtension } from "babylonjs-serializers/glTF/glTFFileExporter";
+    import { Material } from 'babylonjs/Materials/material';
+    import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
     /** @hidden */
     export var __IGLTFExporterExtensionV2: number;
     /**
@@ -65,11 +66,18 @@ declare module "babylonjs-serializers/glTF/2.0/glTFExporterExtension" {
         /**
          * Define this method to modify the default behavior before exporting a texture
          * @param context The context when loading the asset
-         * @param babylonTexture The glTF texture info property
+         * @param babylonTexture The Babylon.js texture
          * @param mimeType The mime-type of the generated image
-         * @returns A promise that resolves with the exported glTF texture info when the export is complete, or null if not handled
+         * @returns A promise that resolves with the exported texture
+         */
+        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
+        /**
+         * Define this method to get notified when a texture info is created
+         * @param context The context when loading the asset
+         * @param textureInfo The glTF texture info
+         * @param babylonTexture The Babylon.js texture
          */
-        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         /**
          * Define this method to modify the default behavior when exporting texture info
          * @param context The context when loading the asset
@@ -78,7 +86,7 @@ declare module "babylonjs-serializers/glTF/2.0/glTFExporterExtension" {
          * @param binaryWriter glTF serializer binary writer instance
          * @returns nullable IMeshPrimitive promise
          */
-        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<IMeshPrimitive>;
         /**
          * Define this method to modify the default behavior when exporting a node
          * @param context The context when exporting the node
@@ -86,7 +94,21 @@ declare module "babylonjs-serializers/glTF/2.0/glTFExporterExtension" {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Promise<INode>;
+        /**
+         * Define this method to modify the default behavior when exporting a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns nullable IMaterial promise
+         */
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
+        /**
+         * Defint this method to return additional textures to export from a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns List of textures
+         */
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
         /**
          * Called after the exporter state changes to EXPORTING
          */
@@ -188,7 +210,8 @@ declare module "babylonjs-serializers/glTF/2.0/glTFMaterialExporter" {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
+        private _finishMaterial;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
@@ -199,7 +222,7 @@ declare module "babylonjs-serializers/glTF/2.0/glTFMaterialExporter" {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         /**
          * Converts an image typed array buffer to a base64 image
          * @param buffer typed array buffer
@@ -298,7 +321,7 @@ declare module "babylonjs-serializers/glTF/2.0/glTFMaterialExporter" {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         private setMetallicRoughnessPbrMaterial;
         private getPixelsFromTexture;
         /**
@@ -495,13 +518,14 @@ declare module "babylonjs-serializers/glTF/2.0/glTFUtilities" {
     }
 }
 declare module "babylonjs-serializers/glTF/2.0/glTFExporter" {
-    import { IBufferView, IAccessor, INode, IMaterial, ITexture, IImage, ISampler, ImageMimeType, IMeshPrimitive, IGLTF } from "babylonjs-gltf2interface";
+    import { IBufferView, IAccessor, INode, IMaterial, ITexture, IImage, ISampler, ImageMimeType, IMeshPrimitive, IGLTF, ITextureInfo } from "babylonjs-gltf2interface";
     import { FloatArray, Nullable } from "babylonjs/types";
     import { Vector3, Vector4 } from "babylonjs/Maths/math";
     import { Node } from "babylonjs/node";
     import { SubMesh } from "babylonjs/Meshes/subMesh";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
     import { Texture } from "babylonjs/Materials/Textures/texture";
+    import { Material } from "babylonjs/Materials/material";
     import { Engine } from "babylonjs/Engines/engine";
     import { Scene } from "babylonjs/scene";
     import { IGLTFExporterExtensionV2 } from "babylonjs-serializers/glTF/2.0/glTFExporterExtension";
@@ -599,10 +623,14 @@ declare module "babylonjs-serializers/glTF/2.0/glTFExporter" {
         private _extensions;
         private static _ExtensionNames;
         private static _ExtensionFactories;
+        private _applyExtension;
         private _applyExtensions;
-        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>>;
-        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
-        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Nullable<BaseTexture>>;
+        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<Nullable<IMeshPrimitive>>;
+        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<Nullable<INode>>;
+        _extensionsPostExportMaterialAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<Nullable<IMaterial>>;
+        _extensionsPostExportMaterialAdditionalTextures(context: string, material: IMaterial, babylonMaterial: Material): BaseTexture[];
+        _extensionsPostExportTextures(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         private _forEachExtensions;
         private _extensionsOnExporting;
         /**
@@ -615,6 +643,7 @@ declare module "babylonjs-serializers/glTF/2.0/glTFExporter" {
          * @param options Options to modify the behavior of the exporter
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
+        dispose(): void;
         /**
          * Registers a glTF exporter extension
          * @param name Name of the extension to export
@@ -709,9 +738,10 @@ declare module "babylonjs-serializers/glTF/2.0/glTFExporter" {
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix Text to use when prefixing a glTF file
+         * @param dispose Dispose the exporter
          * @returns GLTFData with glTF file data
          */
-        _generateGLTFAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLTFAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Creates a binary buffer for glTF
          * @returns array buffer for binary data
@@ -724,12 +754,9 @@ declare module "babylonjs-serializers/glTF/2.0/glTFExporter" {
          */
         private _getPadding;
         /**
-         * Generates a glb file from the json and binary data
-         * Returns an object with the glb file name as the key and data as the value
-         * @param glTFPrefix
-         * @returns object with glb filename as key and data as value
+         * @hidden
          */
-        _generateGLBAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLBAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Sets the TRS for each node
          * @param node glTF Node for storing the transformation data
@@ -1049,7 +1076,6 @@ declare module "babylonjs-serializers/glTF/2.0/shaders/textureTransform.fragment
 }
 declare module "babylonjs-serializers/glTF/2.0/Extensions/KHR_texture_transform" {
     import { ImageMimeType } from "babylonjs-gltf2interface";
-    import { Nullable } from "babylonjs/types";
     import { Texture } from "babylonjs/Materials/Textures/texture";
     import { IGLTFExporterExtensionV2 } from "babylonjs-serializers/glTF/2.0/glTFExporterExtension";
     import { _Exporter } from "babylonjs-serializers/glTF/2.0/glTFExporter";
@@ -1058,6 +1084,7 @@ declare module "babylonjs-serializers/glTF/2.0/Extensions/KHR_texture_transform"
      * @hidden
      */
     export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
+        private _recordedTextures;
         /** Name of this extension */
         readonly name: string;
         /** Defines whether this extension is enabled */
@@ -1068,7 +1095,7 @@ declare module "babylonjs-serializers/glTF/2.0/Extensions/KHR_texture_transform"
         private _exporter;
         constructor(exporter: _Exporter);
         dispose(): void;
-        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
         /**
          * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
          * @param babylonTexture
@@ -1081,7 +1108,6 @@ declare module "babylonjs-serializers/glTF/2.0/Extensions/KHR_texture_transform"
     }
 }
 declare module "babylonjs-serializers/glTF/2.0/Extensions/KHR_lights_punctual" {
-    import { Nullable } from "babylonjs/types";
     import { Node } from "babylonjs/node";
     import { INode } from "babylonjs-gltf2interface";
     import { IGLTFExporterExtensionV2 } from "babylonjs-serializers/glTF/2.0/glTFExporterExtension";
@@ -1112,12 +1138,44 @@ declare module "babylonjs-serializers/glTF/2.0/Extensions/KHR_lights_punctual" {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<INode>;
+    }
+}
+declare module "babylonjs-serializers/glTF/2.0/Extensions/KHR_materials_sheen" {
+    import { ITextureInfo, IMaterial } from "babylonjs-gltf2interface";
+    import { IGLTFExporterExtensionV2 } from "babylonjs-serializers/glTF/2.0/glTFExporterExtension";
+    import { _Exporter } from "babylonjs-serializers/glTF/2.0/glTFExporter";
+    import { Material } from 'babylonjs/Materials/material';
+    import { Texture } from 'babylonjs/Materials/Textures/texture';
+    import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
+    /**
+     * @hidden
+     */
+    export class KHR_materials_sheen implements IGLTFExporterExtensionV2 {
+        /** Name of this extension */
+        readonly name: string;
+        /** Defines whether this extension is enabled */
+        enabled: boolean;
+        /** Defines whether this extension is required */
+        required: boolean;
+        /** Reference to the glTF exporter */
+        private _exporter;
+        private _textureInfo;
+        private _exportedTexture;
+        private _wasUsed;
+        constructor(exporter: _Exporter);
+        dispose(): void;
+        /** @hidden */
+        onExporting(): void;
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void;
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
     }
 }
 declare module "babylonjs-serializers/glTF/2.0/Extensions/index" {
     export * from "babylonjs-serializers/glTF/2.0/Extensions/KHR_texture_transform";
     export * from "babylonjs-serializers/glTF/2.0/Extensions/KHR_lights_punctual";
+    export * from "babylonjs-serializers/glTF/2.0/Extensions/KHR_materials_sheen";
 }
 declare module "babylonjs-serializers/glTF/2.0/index" {
     export * from "babylonjs-serializers/glTF/2.0/glTFAnimation";
@@ -1233,11 +1291,18 @@ declare module BABYLON.GLTF2.Exporter {
         /**
          * Define this method to modify the default behavior before exporting a texture
          * @param context The context when loading the asset
-         * @param babylonTexture The glTF texture info property
+         * @param babylonTexture The Babylon.js texture
          * @param mimeType The mime-type of the generated image
-         * @returns A promise that resolves with the exported glTF texture info when the export is complete, or null if not handled
+         * @returns A promise that resolves with the exported texture
          */
-        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
+        /**
+         * Define this method to get notified when a texture info is created
+         * @param context The context when loading the asset
+         * @param textureInfo The glTF texture info
+         * @param babylonTexture The Babylon.js texture
+         */
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         /**
          * Define this method to modify the default behavior when exporting texture info
          * @param context The context when loading the asset
@@ -1246,7 +1311,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param binaryWriter glTF serializer binary writer instance
          * @returns nullable IMeshPrimitive promise
          */
-        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+        postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<IMeshPrimitive>;
         /**
          * Define this method to modify the default behavior when exporting a node
          * @param context The context when exporting the node
@@ -1254,7 +1319,21 @@ declare module BABYLON.GLTF2.Exporter {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Promise<INode>;
+        /**
+         * Define this method to modify the default behavior when exporting a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns nullable IMaterial promise
+         */
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
+        /**
+         * Defint this method to return additional textures to export from a material
+         * @param material glTF material
+         * @param babylonMaterial BabylonJS material
+         * @returns List of textures
+         */
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
         /**
          * Called after the exporter state changes to EXPORTING
          */
@@ -1348,7 +1427,8 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
+        private _finishMaterial;
         /**
          * Converts a Babylon PBR Metallic Roughness Material to a glTF Material
          * @param babylonPBRMetalRoughMaterial BJS PBR Metallic Roughness Material
@@ -1359,7 +1439,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         /**
          * Converts an image typed array buffer to a base64 image
          * @param buffer typed array buffer
@@ -1458,7 +1538,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param imageData map of image file name to data
          * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
          */
-        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void>;
+        _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial>;
         private setMetallicRoughnessPbrMaterial;
         private getPixelsFromTexture;
         /**
@@ -1740,10 +1820,14 @@ declare module BABYLON.GLTF2.Exporter {
         private _extensions;
         private static _ExtensionNames;
         private static _ExtensionFactories;
+        private _applyExtension;
         private _applyExtensions;
-        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>>;
-        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
-        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Nullable<BaseTexture>>;
+        _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<Nullable<IMeshPrimitive>>;
+        _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<Nullable<INode>>;
+        _extensionsPostExportMaterialAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<Nullable<IMaterial>>;
+        _extensionsPostExportMaterialAdditionalTextures(context: string, material: IMaterial, babylonMaterial: Material): BaseTexture[];
+        _extensionsPostExportTextures(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
         private _forEachExtensions;
         private _extensionsOnExporting;
         /**
@@ -1756,6 +1840,7 @@ declare module BABYLON.GLTF2.Exporter {
          * @param options Options to modify the behavior of the exporter
          */
         constructor(babylonScene: Scene, options?: IExportOptions);
+        dispose(): void;
         /**
          * Registers a glTF exporter extension
          * @param name Name of the extension to export
@@ -1850,9 +1935,10 @@ declare module BABYLON.GLTF2.Exporter {
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix Text to use when prefixing a glTF file
+         * @param dispose Dispose the exporter
          * @returns GLTFData with glTF file data
          */
-        _generateGLTFAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLTFAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Creates a binary buffer for glTF
          * @returns array buffer for binary data
@@ -1865,12 +1951,9 @@ declare module BABYLON.GLTF2.Exporter {
          */
         private _getPadding;
         /**
-         * Generates a glb file from the json and binary data
-         * Returns an object with the glb file name as the key and data as the value
-         * @param glTFPrefix
-         * @returns object with glb filename as key and data as value
+         * @hidden
          */
-        _generateGLBAsync(glTFPrefix: string): Promise<GLTFData>;
+        _generateGLBAsync(glTFPrefix: string, dispose?: boolean): Promise<GLTFData>;
         /**
          * Sets the TRS for each node
          * @param node glTF Node for storing the transformation data
@@ -2186,6 +2269,7 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
      * @hidden
      */
     export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
+        private _recordedTextures;
         /** Name of this extension */
         readonly name: string;
         /** Defines whether this extension is enabled */
@@ -2196,7 +2280,7 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
         private _exporter;
         constructor(exporter: _Exporter);
         dispose(): void;
-        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+        preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
         /**
          * Transform the babylon texture by the offset, rotation and scale parameters using a procedural texture
          * @param babylonTexture
@@ -2235,7 +2319,32 @@ declare module BABYLON.GLTF2.Exporter.Extensions {
          * @param babylonNode BabylonJS node
          * @returns nullable INode promise
          */
-        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+        postExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<INode>;
+    }
+}
+declare module BABYLON.GLTF2.Exporter.Extensions {
+    /**
+     * @hidden
+     */
+    export class KHR_materials_sheen implements IGLTFExporterExtensionV2 {
+        /** Name of this extension */
+        readonly name: string;
+        /** Defines whether this extension is enabled */
+        enabled: boolean;
+        /** Defines whether this extension is required */
+        required: boolean;
+        /** Reference to the glTF exporter */
+        private _exporter;
+        private _textureInfo;
+        private _exportedTexture;
+        private _wasUsed;
+        constructor(exporter: _Exporter);
+        dispose(): void;
+        /** @hidden */
+        onExporting(): void;
+        postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void;
+        postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
+        postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
     }
 }
 declare module BABYLON {

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

@@ -44142,7 +44142,7 @@ declare module "babylonjs/Gamepads/Controllers/windowsMotionController" {
         /**
          * holds the thumbstick values (X,Y)
          */
-        readonly thumbstickValues: StickValues;
+        thumbstickValues: StickValues;
         /**
          * Fired when the thumbstick on this controller is clicked
          */
@@ -111549,7 +111549,7 @@ declare module BABYLON {
         /**
          * holds the thumbstick values (X,Y)
          */
-        readonly thumbstickValues: StickValues;
+        thumbstickValues: StickValues;
         /**
          * Fired when the thumbstick on this controller is clicked
          */

Разница между файлами не показана из-за своего большого размера
+ 6 - 6
dist/preview release/viewer/babylon.viewer.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 3 - 0
nodeEditor/src/components/propertyTab/propertyTabComponent.tsx

@@ -15,6 +15,8 @@ import { SliderLineComponent } from '../../sharedComponents/sliderLineComponent'
 import { GraphFrame } from '../../diagram/graphFrame';
 import { TextInputLineComponent } from '../../sharedComponents/textInputLineComponent';
 import { Color3LineComponent } from '../../sharedComponents/color3LineComponent';
+import { TextLineComponent } from '../../sharedComponents/textLineComponent';
+import { Engine } from 'babylonjs/Engines/engine';
 require("./propertyTab.scss");
 
 interface IPropertyTabComponentProps {
@@ -110,6 +112,7 @@ export class PropertyTabComponent extends React.Component<IPropertyTabComponentP
                 </div>
                 <div>
                     <LineContainerComponent title="GENERAL">
+                        <TextLineComponent label="Version" value={Engine.Version}/>
                         <ButtonLineComponent label="Reset to default" onClick={() => {
                             this.props.globalState.nodeMaterial!.setToDefault();
                             this.props.globalState.onResetRequiredObservable.notifyObservers();

+ 1 - 2
serializers/src/glTF/2.0/Extensions/KHR_lights_punctual.ts

@@ -1,6 +1,5 @@
 import { SpotLight } from "babylonjs/Lights/spotLight";
 import { Vector3, Color3, Quaternion } from "babylonjs/Maths/math";
-import { Nullable } from "babylonjs/types";
 import { Light } from "babylonjs/Lights/light";
 import { Node } from "babylonjs/node";
 import { ShadowLight } from "babylonjs/Lights/shadowLight";
@@ -97,7 +96,7 @@ export class KHR_lights_punctual implements IGLTFExporterExtensionV2 {
      * @param babylonNode BabylonJS node
      * @returns nullable INode promise
      */
-    public postExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>> {
+    public postExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<INode> {
         return new Promise((resolve, reject) => {
             if (babylonNode instanceof ShadowLight) {
                 const babylonLight: ShadowLight = babylonNode;

+ 115 - 0
serializers/src/glTF/2.0/Extensions/KHR_materials_sheen.ts

@@ -0,0 +1,115 @@
+import { ITextureInfo, IMaterial } from "babylonjs-gltf2interface";
+import { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
+import { _Exporter } from "../glTFExporter";
+import { Material } from 'babylonjs/Materials/material';
+import { PBRMaterial } from 'babylonjs/Materials/PBR/pbrMaterial';
+import { Texture } from 'babylonjs/Materials/Textures/texture';
+import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
+import { Nullable } from 'babylonjs/types';
+
+const NAME = "KHR_materials_sheen";
+
+interface IKHR_materials_sheen {
+    intensityFactor: number;
+    colorFactor: number[];
+    colorIntensityTexture?: ITextureInfo;
+}
+
+/**
+ * @hidden
+ */
+export class KHR_materials_sheen implements IGLTFExporterExtensionV2 {
+    /** Name of this extension */
+    public readonly name = NAME;
+
+    /** Defines whether this extension is enabled */
+    public enabled = true;
+
+    /** Defines whether this extension is required */
+    public required = false;
+
+    /** Reference to the glTF exporter */
+    private _exporter: _Exporter;
+    private _textureInfo: ITextureInfo;
+    private _exportedTexture: Nullable<BaseTexture> = null;
+
+    private _wasUsed = false;
+
+    constructor(exporter: _Exporter) {
+        this._exporter = exporter;
+    }
+
+    public dispose() {
+        delete this._exporter;
+    }
+
+    /** @hidden */
+    public onExporting(): void {
+        if (this._wasUsed) {
+            if (this._exporter._glTF.extensionsUsed == null) {
+                this._exporter._glTF.extensionsUsed = [];
+            }
+            if (this._exporter._glTF.extensionsUsed.indexOf(NAME) === -1) {
+                this._exporter._glTF.extensionsUsed.push(NAME);
+            }
+            if (this.required) {
+                if (this._exporter._glTF.extensionsRequired == null) {
+                    this._exporter._glTF.extensionsRequired = [];
+                }
+                if (this._exporter._glTF.extensionsRequired.indexOf(NAME) === -1) {
+                    this._exporter._glTF.extensionsRequired.push(NAME);
+                }
+            }
+            if (this._exporter._glTF.extensions == null) {
+                this._exporter._glTF.extensions = {};
+            }
+        }
+    }
+
+    public postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void {
+        if (babylonTexture === this._exportedTexture || babylonTexture.reservedDataStore && babylonTexture.reservedDataStore.source === this._exportedTexture) {
+            this._textureInfo = textureInfo;
+        }
+    }
+
+    public postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[] {
+        if (babylonMaterial instanceof PBRMaterial) {
+            if (babylonMaterial.sheen.isEnabled && babylonMaterial.sheen.texture) {
+                this._exportedTexture = babylonMaterial.sheen.texture;
+                return [babylonMaterial.sheen.texture];
+            }
+        }
+
+        return [];
+    }
+
+    public postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial> {
+        return new Promise((resolve, reject) => {
+            if (babylonMaterial instanceof PBRMaterial) {
+                if (!babylonMaterial.sheen.isEnabled) {
+                    resolve(node);
+                    return;
+                }
+
+                this._wasUsed = true;
+
+                if (node.extensions == null) {
+                    node.extensions = {};
+                }
+                const sheenInfo: IKHR_materials_sheen = {
+                    colorFactor: babylonMaterial.sheen.color.asArray(),
+                    intensityFactor: babylonMaterial.sheen.intensity
+                };
+
+                if (this._textureInfo) {
+                    sheenInfo.colorIntensityTexture = this._textureInfo;
+                }
+
+                node.extensions[NAME] = sheenInfo;
+            }
+            resolve(node);
+        });
+    }
+}
+
+_Exporter.RegisterExtension(NAME, (exporter) => new KHR_materials_sheen(exporter));

+ 19 - 3
serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts

@@ -1,6 +1,4 @@
 import { ImageMimeType } from "babylonjs-gltf2interface";
-
-import { Nullable } from "babylonjs/types";
 import { Tools } from "babylonjs/Misc/tools";
 import { Texture } from "babylonjs/Materials/Textures/texture";
 import { ProceduralTexture } from "babylonjs/Materials/Textures/Procedurals/proceduralTexture";
@@ -28,6 +26,8 @@ interface IKHRTextureTransform {
  * @hidden
  */
 export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
+    private _recordedTextures: ProceduralTexture[] = [];
+
     /** Name of this extension */
     public readonly name = NAME;
 
@@ -45,10 +45,14 @@ export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
     }
 
     public dispose() {
+        for (var texture of this._recordedTextures) {
+            texture.dispose();
+        }
+
         delete this._exporter;
     }
 
-    public preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>> {
+    public preExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture> {
         return new Promise((resolve, reject) => {
             const scene = babylonTexture.getScene();
             if (!scene) {
@@ -72,6 +76,10 @@ export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
                 texture_transform_extension.rotation = babylonTexture.wAng;
             }
 
+            if (babylonTexture.coordinatesIndex !== 0) {
+                texture_transform_extension.texCoord = babylonTexture.coordinatesIndex;
+            }
+
             if (!Object.keys(texture_transform_extension).length) {
                 resolve(babylonTexture);
                 return;
@@ -103,6 +111,14 @@ export class KHR_texture_transform implements IGLTFExporterExtensionV2 {
                 resolve(babylonTexture);
             }
 
+            proceduralTexture.reservedDataStore = {
+                hidden: true,
+                source: babylonTexture
+            };
+
+            this._recordedTextures.push(proceduralTexture);
+
+            proceduralTexture.coordinatesIndex = babylonTexture.coordinatesIndex;
             proceduralTexture.setTexture("textureSampler", babylonTexture);
             proceduralTexture.setMatrix("textureTransformMat", babylonTexture.getTextureMatrix());
 

+ 2 - 1
serializers/src/glTF/2.0/Extensions/index.ts

@@ -1,2 +1,3 @@
 export * from "./KHR_texture_transform";
-export * from "./KHR_lights_punctual";
+export * from "./KHR_lights_punctual";
+export * from "./KHR_materials_sheen";

+ 76 - 35
serializers/src/glTF/2.0/glTFExporter.ts

@@ -1,4 +1,4 @@
-import { AccessorType, IBufferView, IAccessor, INode, IScene, IMesh, IMaterial, ITexture, IImage, ISampler, IAnimation, ImageMimeType, IMeshPrimitive, IBuffer, IGLTF, MeshPrimitiveMode, AccessorComponentType } from "babylonjs-gltf2interface";
+import { AccessorType, IBufferView, IAccessor, INode, IScene, IMesh, IMaterial, ITexture, IImage, ISampler, IAnimation, ImageMimeType, IMeshPrimitive, IBuffer, IGLTF, MeshPrimitiveMode, AccessorComponentType, ITextureInfo } from "babylonjs-gltf2interface";
 
 import { FloatArray, Nullable, IndicesArray } from "babylonjs/types";
 import { Viewport, Color3, Vector2, Vector3, Vector4, Quaternion } from "babylonjs/Maths/math";
@@ -142,43 +142,67 @@ export class _Exporter {
     private static _ExtensionNames = new Array<string>();
     private static _ExtensionFactories: { [name: string]: (exporter: _Exporter) => IGLTFExporterExtensionV2 } = {};
 
-    private _applyExtensions<T>(property: any, actionAsync: (extension: IGLTFExporterExtensionV2) => Nullable<T> | undefined): Nullable<T> {
+    private _applyExtension<T>(node: T, extensions: IGLTFExporterExtensionV2[], index: number, actionAsync: (extension: IGLTFExporterExtensionV2, node: T) => Promise<Nullable<T>> | undefined): Promise<Nullable<T>> {
+        if (index >= extensions.length) {
+            return Promise.resolve(node);
+        }
+
+        let currentPromise = actionAsync(extensions[index], node);
+
+        if (!currentPromise) {
+            return this._applyExtension(node, extensions, index + 1, actionAsync);
+        }
+
+        return currentPromise.then((newNode) => this._applyExtension(newNode || node, extensions, index + 1, actionAsync));
+    }
+
+    private _applyExtensions<T>(node: T, actionAsync: (extension: IGLTFExporterExtensionV2, node: T) => Promise<Nullable<T>> | undefined): Promise<Nullable<T>> {
+        var extensions: IGLTFExporterExtensionV2[] = [];
         for (const name of _Exporter._ExtensionNames) {
-            const extension = this._extensions[name];
-            if (extension.enabled) {
-                const exporterProperty = property as any;
-                exporterProperty._activeLoaderExtensions = exporterProperty._activeLoaderExtensions || {};
-                const activeLoaderExtensions = exporterProperty._activeLoaderExtensions;
-                if (!activeLoaderExtensions[name]) {
-                    activeLoaderExtensions[name] = true;
-
-                    try {
-                        const result = actionAsync(extension);
-                        if (result) {
-                            return result;
-                        }
-                    }
-                    finally {
-                        delete activeLoaderExtensions[name];
-                        delete exporterProperty._activeLoaderExtensions;
-                    }
-                }
-            }
+            extensions.push(this._extensions[name]);
         }
 
-        return null;
+        return this._applyExtension(node, extensions, 0, actionAsync);
+    }
+
+    public _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Nullable<BaseTexture>> {
+        return this._applyExtensions(babylonTexture, (extension, node) => extension.preExportTextureAsync && extension.preExportTextureAsync(context, node, mimeType));
+    }
+
+    public _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<Nullable<IMeshPrimitive>> {
+        return this._applyExtensions(meshPrimitive, (extension, node) => extension.postExportMeshPrimitiveAsync && extension.postExportMeshPrimitiveAsync(context, node, babylonSubMesh, binaryWriter));
+    }
+
+    public _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Promise<Nullable<INode>> {
+        return this._applyExtensions(node, (extension, node) => extension.postExportNodeAsync && extension.postExportNodeAsync(context, node, babylonNode));
     }
 
-    public _extensionsPreExportTextureAsync(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<BaseTexture>> {
-        return this._applyExtensions(babylonTexture, (extension) => extension.preExportTextureAsync && extension.preExportTextureAsync(context, babylonTexture, mimeType));
+    public _extensionsPostExportMaterialAsync(context: string, material: IMaterial, babylonMaterial: Material): Promise<Nullable<IMaterial>> {
+        return this._applyExtensions(material, (extension, node) => extension.postExportMaterialAsync && extension.postExportMaterialAsync(context, node, babylonMaterial));
     }
 
-    public _extensionsPostExportMeshPrimitiveAsync(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>> {
-        return this._applyExtensions(meshPrimitive, (extension) => extension.postExportMeshPrimitiveAsync && extension.postExportMeshPrimitiveAsync(context, meshPrimitive, babylonSubMesh, binaryWriter));
+    public _extensionsPostExportMaterialAdditionalTextures(context: string, material: IMaterial, babylonMaterial: Material): BaseTexture[] {
+        let output: BaseTexture[] = [];
+
+        for (const name of _Exporter._ExtensionNames) {
+            var extension = this._extensions[name];
+
+            if (extension.postExportMaterialAdditionalTextures) {
+                output.push(...extension.postExportMaterialAdditionalTextures(context, material, babylonMaterial));
+            }
+        }
+
+        return output;
     }
 
-    public _extensionsPostExportNodeAsync(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>> {
-        return this._applyExtensions(node, (extension) => extension.postExportNodeAsync && extension.postExportNodeAsync(context, node, babylonNode));
+    public _extensionsPostExportTextures(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void {
+        for (const name of _Exporter._ExtensionNames) {
+            var extension = this._extensions[name];
+
+            if (extension.postExportTexture) {
+                extension.postExportTexture(context, textureInfo, babylonTexture);
+            }
+        }
     }
 
     private _forEachExtensions(action: (extension: IGLTFExporterExtensionV2) => void): void {
@@ -234,6 +258,14 @@ export class _Exporter {
         this._loadExtensions();
     }
 
+    public dispose() {
+        for (var extensionKey in this._extensions) {
+            const extension = this._extensions[extensionKey];
+
+            extension.dispose();
+        }
+    }
+
     /**
      * Registers a glTF exporter extension
      * @param name Name of the extension to export
@@ -749,9 +781,10 @@ export class _Exporter {
     /**
      * Generates data for .gltf and .bin files based on the glTF prefix string
      * @param glTFPrefix Text to use when prefixing a glTF file
+     * @param dispose Dispose the exporter
      * @returns GLTFData with glTF file data
      */
-    public _generateGLTFAsync(glTFPrefix: string): Promise<GLTFData> {
+    public _generateGLTFAsync(glTFPrefix: string, dispose = true): Promise<GLTFData> {
         return this._generateBinaryAsync().then((binaryBuffer) => {
             this._extensionsOnExporting();
             const jsonText = this.generateJSON(false, glTFPrefix, true);
@@ -771,6 +804,10 @@ export class _Exporter {
                 }
             }
 
+            if (dispose) {
+                this.dispose();
+            }
+
             return container;
         });
 
@@ -803,12 +840,9 @@ export class _Exporter {
     }
 
     /**
-     * Generates a glb file from the json and binary data
-     * Returns an object with the glb file name as the key and data as the value
-     * @param glTFPrefix
-     * @returns object with glb filename as key and data as value
+     * @hidden
      */
-    public _generateGLBAsync(glTFPrefix: string): Promise<GLTFData> {
+    public _generateGLBAsync(glTFPrefix: string, dispose = true): Promise<GLTFData> {
         return this._generateBinaryAsync().then((binaryBuffer) => {
             this._extensionsOnExporting();
             const jsonText = this.generateJSON(true);
@@ -890,6 +924,10 @@ export class _Exporter {
                 this._localEngine.dispose();
             }
 
+            if (dispose) {
+                this.dispose();
+            }
+
             return container;
         });
     }
@@ -1331,6 +1369,9 @@ export class _Exporter {
                         }
                         else {
                             return promise.then((node) => {
+                                if (!node) {
+                                    return;
+                                }
                                 this._nodes.push(node);
                                 nodeIndex = this._nodes.length - 1;
                                 nodeMap[babylonNode.uniqueId] = nodeIndex;

+ 32 - 7
serializers/src/glTF/2.0/glTFExporterExtension.ts

@@ -1,13 +1,14 @@
-import { ImageMimeType, IMeshPrimitive, INode } from "babylonjs-gltf2interface";
+import { ImageMimeType, IMeshPrimitive, INode, IMaterial, ITextureInfo } from "babylonjs-gltf2interface";
 import { Node } from "babylonjs/node";
 
-import { Nullable } from "babylonjs/types";
 import { Texture } from "babylonjs/Materials/Textures/texture";
 import { SubMesh } from "babylonjs/Meshes/subMesh";
 import { IDisposable } from "babylonjs/scene";
 
 import { _BinaryWriter } from "./glTFExporter";
 import { IGLTFExporterExtension } from "../glTFFileExporter";
+import { Material } from 'babylonjs/Materials/material';
+import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
 
 /** @hidden */
 export var __IGLTFExporterExtensionV2 = 0; // I am here to allow dts to be created
@@ -20,11 +21,19 @@ export interface IGLTFExporterExtensionV2 extends IGLTFExporterExtension, IDispo
     /**
      * Define this method to modify the default behavior before exporting a texture
      * @param context The context when loading the asset
-     * @param babylonTexture The glTF texture info property
+     * @param babylonTexture The Babylon.js texture
      * @param mimeType The mime-type of the generated image
-     * @returns A promise that resolves with the exported glTF texture info when the export is complete, or null if not handled
+     * @returns A promise that resolves with the exported texture
      */
-    preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Nullable<Promise<Texture>>;
+    preExportTextureAsync?(context: string, babylonTexture: Texture, mimeType: ImageMimeType): Promise<Texture>;
+
+    /**
+     * Define this method to get notified when a texture info is created
+     * @param context The context when loading the asset
+     * @param textureInfo The glTF texture info
+     * @param babylonTexture The Babylon.js texture
+     */
+    postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: BaseTexture): void;
 
     /**
      * Define this method to modify the default behavior when exporting texture info
@@ -34,7 +43,7 @@ export interface IGLTFExporterExtensionV2 extends IGLTFExporterExtension, IDispo
      * @param binaryWriter glTF serializer binary writer instance
      * @returns nullable IMeshPrimitive promise
      */
-    postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Nullable<Promise<IMeshPrimitive>>;
+    postExportMeshPrimitiveAsync?(context: string, meshPrimitive: IMeshPrimitive, babylonSubMesh: SubMesh, binaryWriter: _BinaryWriter): Promise<IMeshPrimitive>;
 
     /**
      * Define this method to modify the default behavior when exporting a node
@@ -43,7 +52,23 @@ export interface IGLTFExporterExtensionV2 extends IGLTFExporterExtension, IDispo
      * @param babylonNode BabylonJS node
      * @returns nullable INode promise
      */
-    postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Nullable<Promise<INode>>;
+    postExportNodeAsync?(context: string, node: INode, babylonNode: Node): Promise<INode>;
+
+    /**
+     * Define this method to modify the default behavior when exporting a material
+     * @param material glTF material
+     * @param babylonMaterial BabylonJS material
+     * @returns nullable IMaterial promise
+     */
+    postExportMaterialAsync?(context: string, node: IMaterial, babylonMaterial: Material): Promise<IMaterial>;
+
+    /**
+     * Defint this method to return additional textures to export from a material
+     * @param material glTF material
+     * @param babylonMaterial BabylonJS material
+     * @returns List of textures
+     */
+    postExportMaterialAdditionalTextures?(context: string, node: IMaterial, babylonMaterial: Material): BaseTexture[];
 
     /**
      * Called after the exporter state changes to EXPORTING

+ 40 - 9
serializers/src/glTF/2.0/glTFMaterialExporter.ts

@@ -122,7 +122,7 @@ export class _GLTFMaterialExporter {
      * @param hasTextureCoords specifies if texture coordinates are present on the material
      */
     public _convertMaterialsToGLTFAsync(babylonMaterials: Material[], mimeType: ImageMimeType, hasTextureCoords: boolean) {
-        let promises: Promise<void>[] = [];
+        let promises: Promise<IMaterial>[] = [];
         for (let babylonMaterial of babylonMaterials) {
             if (babylonMaterial instanceof StandardMaterial) {
                 promises.push(this._convertStandardMaterialAsync(babylonMaterial, mimeType, hasTextureCoords));
@@ -290,7 +290,7 @@ export class _GLTFMaterialExporter {
      * @param imageData map of image file name to data
      * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
      */
-    public _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void> {
+    public _convertStandardMaterialAsync(babylonStandardMaterial: StandardMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
         const materialMap = this._exporter._materialMap;
         const materials = this._exporter._materials;
         const promises = [];
@@ -361,7 +361,34 @@ export class _GLTFMaterialExporter {
         materials.push(glTFMaterial);
         materialMap[babylonStandardMaterial.uniqueId] = materials.length - 1;
 
-        return Promise.all(promises).then(() => { /* do nothing */ });
+        return this._finishMaterial(promises, glTFMaterial, babylonStandardMaterial, mimeType);
+    }
+
+    private _finishMaterial<T>(promises: Promise<T>[], glTFMaterial: IMaterial, babylonMaterial: Material, mimeType: ImageMimeType) {
+        return Promise.all(promises).then(() => {
+
+            const textures = this._exporter._extensionsPostExportMaterialAdditionalTextures("exportMaterial", glTFMaterial, babylonMaterial);
+            let tasks: Nullable<Promise<Nullable<ITextureInfo>>[]> = null;
+
+            for (var texture of textures) {
+                if (!tasks) {
+                    tasks = [];
+                }
+                tasks.push(this._exportTextureAsync(texture, mimeType));
+            }
+
+            if (!tasks) {
+                tasks = [Promise.resolve(null)];
+            }
+
+            return Promise.all(tasks).then(() => {
+                let extensionWork = this._exporter._extensionsPostExportMaterialAsync("exportMaterial", glTFMaterial, babylonMaterial);
+                if (!extensionWork) {
+                    return glTFMaterial;
+                }
+                return extensionWork.then(() => glTFMaterial);
+            });
+        });
     }
 
     /**
@@ -374,7 +401,7 @@ export class _GLTFMaterialExporter {
      * @param imageData map of image file name to data
      * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
      */
-    public _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void> {
+    public _convertPBRMetallicRoughnessMaterialAsync(babylonPBRMetalRoughMaterial: PBRMetallicRoughnessMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
         const materialMap = this._exporter._materialMap;
         const materials = this._exporter._materials;
         let promises: Promise<void>[] = [];
@@ -452,7 +479,7 @@ export class _GLTFMaterialExporter {
         materials.push(glTFMaterial);
         materialMap[babylonPBRMetalRoughMaterial.uniqueId] = materials.length - 1;
 
-        return Promise.all(promises).then(() => { /* do nothing */ });
+        return this._finishMaterial(promises, glTFMaterial, babylonPBRMetalRoughMaterial, mimeType);
     }
 
     /**
@@ -1001,7 +1028,7 @@ export class _GLTFMaterialExporter {
      * @param imageData map of image file name to data
      * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
      */
-    public _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void> {
+    public _convertPBRMaterialAsync(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
         const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {};
         const glTFMaterial: IMaterial = {
             name: babylonPBRMaterial.name
@@ -1028,7 +1055,7 @@ export class _GLTFMaterialExporter {
         }
     }
 
-    private setMetallicRoughnessPbrMaterial(metallicRoughness: Nullable<_IPBRMetallicRoughness>, babylonPBRMaterial: PBRMaterial, glTFMaterial: IMaterial, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<void> {
+    private setMetallicRoughnessPbrMaterial(metallicRoughness: Nullable<_IPBRMetallicRoughness>, babylonPBRMaterial: PBRMaterial, glTFMaterial: IMaterial, glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness, mimeType: ImageMimeType, hasTextureCoords: boolean): Promise<IMaterial> {
         const materialMap = this._exporter._materialMap;
         const materials = this._exporter._materials;
         let promises = [];
@@ -1075,7 +1102,8 @@ export class _GLTFMaterialExporter {
                     let promise = this._exportTextureAsync(babylonPBRMaterial.ambientTexture, mimeType).then((glTFTexture) => {
                         if (glTFTexture) {
                             let occlusionTexture: IMaterialOcclusionTextureInfo = {
-                                index: glTFTexture.index
+                                index: glTFTexture.index,
+                                texCoord: glTFTexture.texCoord
                             };
 
                             glTFMaterial.occlusionTexture = occlusionTexture;
@@ -1105,7 +1133,8 @@ export class _GLTFMaterialExporter {
             materials.push(glTFMaterial);
             materialMap[babylonPBRMaterial.uniqueId] = materials.length - 1;
         }
-        return Promise.all(promises).then((result) => { /* do nothing */ });
+
+        return this._finishMaterial(promises, glTFMaterial, babylonPBRMaterial, mimeType);
     }
 
     private getPixelsFromTexture(babylonTexture: BaseTexture): Uint8Array | Float32Array {
@@ -1168,7 +1197,9 @@ export class _GLTFMaterialExporter {
                     const textureInfo = this._getTextureInfoFromBase64(base64Data, babylonTexture.name.replace(/\.\/|\/|\.\\|\\/g, "_"), mimeType, babylonTexture.coordinatesIndex, samplerIndex);
                     if (textureInfo) {
                         this._textureMap[textureUid] = textureInfo;
+                        this._exporter._extensionsPostExportTextures("linkTextureInfo", textureInfo, babylonTexture);
                     }
+
                     return textureInfo;
                 });
             }

+ 2 - 4
src/Gamepads/Controllers/windowsMotionController.ts

@@ -597,9 +597,7 @@ export class XRWindowsMotionController extends WindowsMotionController {
     /**
      * holds the thumbstick values (X,Y)
      */
-    public get thumbstickValues(): StickValues {
-        return this.rightStick;
-    }
+    public thumbstickValues: StickValues = { x: 0, y: 0 };
 
     /**
      * Fired when the thumbstick on this controller is clicked
@@ -659,4 +657,4 @@ PoseEnabledControllerHelper._ControllerFactories.push({
     create: (gamepadInfo) => {
         return new WindowsMotionController(gamepadInfo);
     }
-});
+});

+ 1 - 1
src/Meshes/mesh.ts

@@ -1693,7 +1693,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
     public render(subMesh: SubMesh, enableAlphaMode: boolean, effectiveMeshReplacement?: AbstractMesh): Mesh {
         var scene = this.getScene();
 
-        if (scene._isInIntermediateRendering()) {
+        if (this._internalAbstractMeshDataInfo._isActiveIntermediate) {
             this._internalAbstractMeshDataInfo._isActiveIntermediate = false;
         } else {
             this._internalAbstractMeshDataInfo._isActive = false;