Sfoglia il codice sorgente

Merge remote-tracking branch 'refs/remotes/BabylonJS/master' into subEmitter2

# Conflicts:
#	dist/preview release/what's new.md
Ibraheem Osama 7 anni fa
parent
commit
4aa21464ff
100 ha cambiato i file con 36694 aggiunte e 28916 eliminazioni
  1. 7567 7313
      Playground/babylon.d.txt
  2. BIN
      Playground/scenes/Alien/Alien.bin
  3. 1562 0
      Playground/scenes/Alien/Alien.gltf
  4. BIN
      Playground/scenes/Alien/Alien_baseColor.png
  5. BIN
      Playground/scenes/Alien/Alien_normal.png
  6. BIN
      Playground/scenes/Alien/Alien_occlusionRoughnessMetallic.png
  7. BIN
      Playground/scenes/TwoQuads/LOD0.png
  8. BIN
      Playground/scenes/TwoQuads/LOD1.png
  9. BIN
      Playground/scenes/TwoQuads/LOD2.png
  10. BIN
      Playground/scenes/TwoQuads/TwoQuads.bin
  11. 160 0
      Playground/scenes/TwoQuads/TwoQuads.gltf
  12. 46 11
      Tools/Gulp/config.json
  13. 4 3
      Tools/Gulp/gulp-addDtsExport.js
  14. 23 29
      Tools/Gulp/gulp-addModuleExports.js
  15. 3 6
      Tools/Gulp/gulpfile.js
  16. 7 7
      Tools/Gulp/package.json
  17. 5 5
      Tools/Gulp/readme.md
  18. 14 1
      Tools/Publisher/index.js
  19. 1 1
      Viewer/src/configuration/configuration.ts
  20. 6 2
      Viewer/src/templateManager.ts
  21. 4 5
      Viewer/src/viewer/defaultViewer.ts
  22. 0 2
      Viewer/src/viewer/viewer.ts
  23. 12345 12008
      dist/preview release/babylon.d.ts
  24. 57 57
      dist/preview release/babylon.js
  25. 956 135
      dist/preview release/babylon.max.js
  26. 58 58
      dist/preview release/babylon.worker.js
  27. 8084 7747
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  28. 60 59
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  29. 956 141
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  30. 941 124
      dist/preview release/customConfigurations/minimalGLTFViewer/es6.js
  31. 941 118
      dist/preview release/es6.js
  32. 248 0
      dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts
  33. 28 0
      dist/preview release/gltf2Interface/package.json
  34. 13 5
      dist/preview release/gui/babylon.gui.d.ts
  35. 96 41
      dist/preview release/gui/babylon.gui.js
  36. 4 3
      dist/preview release/gui/babylon.gui.min.js
  37. 13 5
      dist/preview release/gui/babylon.gui.module.d.ts
  38. 1 1
      dist/preview release/gui/package.json
  39. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  40. 21 2
      dist/preview release/inspector/babylon.inspector.d.ts
  41. 159 8
      dist/preview release/inspector/babylon.inspector.js
  42. 4 4
      dist/preview release/inspector/babylon.inspector.min.js
  43. 1 1
      dist/preview release/inspector/package.json
  44. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  45. 17 8
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  46. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  47. 17 8
      dist/preview release/loaders/babylon.glTFFileLoader.js
  48. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  49. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  50. 31 28
      dist/preview release/loaders/babylonjs.loaders.js
  51. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  52. 1 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  53. 4 1
      dist/preview release/loaders/package.json
  54. 1 0
      dist/preview release/materialsLibrary/babylon.customMaterial.d.ts
  55. 1 0
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  56. 2 2
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  57. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  58. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  59. 15 20
      dist/preview release/materialsLibrary/babylonjs.materials.js
  60. 7 7
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  61. 1 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  62. 1 1
      dist/preview release/materialsLibrary/package.json
  63. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  64. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  65. 14 20
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.js
  66. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  67. 1 1
      dist/preview release/postProcessesLibrary/package.json
  68. 14 20
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js
  69. 1 1
      dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js
  70. 1 1
      dist/preview release/proceduralTexturesLibrary/package.json
  71. 42 0
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  72. 262 31
      dist/preview release/serializers/babylon.glTF2Serializer.js
  73. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  74. 276 51
      dist/preview release/serializers/babylonjs.serializers.js
  75. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  76. 43 249
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  77. 4 1
      dist/preview release/serializers/package.json
  78. 12 121
      dist/preview release/typedocValidationBaseline.json
  79. 70 70
      dist/preview release/viewer/babylon.viewer.js
  80. 1077 259
      dist/preview release/viewer/babylon.viewer.max.js
  81. 1 4
      dist/preview release/viewer/package.json
  82. 17 4
      dist/preview release/what's new.md
  83. 17 2
      gui/src/advancedDynamicTexture.ts
  84. 2 2
      gui/src/controls/button.ts
  85. 2 2
      gui/src/controls/colorpicker.ts
  86. 2 0
      gui/src/controls/container.ts
  87. 47 9
      gui/src/controls/control.ts
  88. 2 2
      gui/src/controls/inputText.ts
  89. 2 2
      gui/src/controls/slider.ts
  90. 17 3
      gui/src/valueAndUnit.ts
  91. 62 14
      inspector/src/details/DetailPanel.ts
  92. 84 3
      inspector/src/details/PropertyLine.ts
  93. 39 3
      inspector/src/gui/SearchBar.ts
  94. 17 6
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  95. 3 2
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  96. 1 0
      materialsLibrary/src/custom/babylon.customMaterial.ts
  97. 1 1
      package.json
  98. 10 1
      sandbox/index.js
  99. 43 32
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  100. 0 0
      serializers/src/glTF/2.0/babylon.glTFMaterial.ts

File diff suppressed because it is too large
+ 7567 - 7313
Playground/babylon.d.txt


BIN
Playground/scenes/Alien/Alien.bin


File diff suppressed because it is too large
+ 1562 - 0
Playground/scenes/Alien/Alien.gltf


BIN
Playground/scenes/Alien/Alien_baseColor.png


BIN
Playground/scenes/Alien/Alien_normal.png


BIN
Playground/scenes/Alien/Alien_occlusionRoughnessMetallic.png


BIN
Playground/scenes/TwoQuads/LOD0.png


BIN
Playground/scenes/TwoQuads/LOD1.png


BIN
Playground/scenes/TwoQuads/LOD2.png


BIN
Playground/scenes/TwoQuads/TwoQuads.bin


+ 160 - 0
Playground/scenes/TwoQuads/TwoQuads.gltf

@@ -0,0 +1,160 @@
+{
+  "accessors": [
+    {
+      "bufferView": 0,
+      "componentType": 5126,
+      "count": 4,
+      "type": "VEC3",
+      "max": [
+        0.5,
+        0.5,
+        0.0
+      ],
+      "min": [
+        -0.5,
+        -0.5,
+        0.0
+      ]
+    },
+    {
+      "bufferView": 1,
+      "componentType": 5126,
+      "count": 4,
+      "type": "VEC2"
+    },
+    {
+      "bufferView": 2,
+      "componentType": 5125,
+      "count": 6,
+      "type": "SCALAR"
+    }
+  ],
+  "asset": {
+    "version": "2.0"
+  },
+  "buffers": [
+    {
+      "uri": "TwoQuads.bin",
+      "byteLength": 104
+    }
+  ],
+  "bufferViews": [
+    {
+      "buffer": 0,
+      "byteLength": 48
+    },
+    {
+      "buffer": 0,
+      "byteOffset": 48,
+      "byteLength": 32
+    },
+    {
+      "buffer": 0,
+      "byteOffset": 80,
+      "byteLength": 24
+    }
+  ],
+  "extensionsUsed": [
+    "MSFT_lod"
+  ],
+  "images": [
+    {
+      "uri": "LOD0.png"
+    },
+    {
+      "uri": "LOD1.png"
+    },
+    {
+      "uri": "LOD2.png"
+    }
+  ],
+  "materials": [
+    {
+      "name": "LOD0",
+      "pbrMetallicRoughness": {
+        "baseColorTexture": {
+          "index": 0
+        },
+        "metallicFactor": 0
+      },
+      "extensions": {
+        "MSFT_lod": {
+          "ids": [
+            1,
+            2
+          ]
+        }
+      }
+    },
+    {
+      "name": "LOD1",
+      "pbrMetallicRoughness": {
+        "baseColorTexture": {
+          "index": 1
+        },
+        "metallicFactor": 0
+      }
+    },
+    {
+      "name": "LOD2",
+      "pbrMetallicRoughness": {
+        "baseColorTexture": {
+          "index": 2
+        },
+        "metallicFactor": 0
+      }
+    }
+  ],
+  "meshes": [
+    {
+      "primitives": [
+        {
+          "attributes": {
+            "POSITION": 0,
+            "TEXCOORD_0": 1
+          },
+          "indices": 2,
+          "material": 0
+        }
+      ]
+    }
+  ],
+  "nodes": [
+    {
+      "mesh": 0,
+      "translation": [
+        -0.55,
+        0,
+        0
+      ]
+    },
+    {
+      "mesh": 0,
+      "translation": [
+        0.55,
+        0,
+        0
+      ]
+    }
+  ],
+  "scene": 0,
+  "scenes": [
+    {
+      "nodes": [
+        0,
+        1
+      ]
+    }
+  ],
+  "textures": [
+    {
+      "source": 0
+    },
+    {
+      "source": 1
+    },
+    {
+      "source": 2
+    }
+  ]
+}

+ 46 - 11
Tools/Gulp/config.json

@@ -385,6 +385,7 @@
         },
         "animations": {
             "files": [
+                "../../src/Animations/babylon.animationPropertiesOverride.js",
                 "../../src/Animations/babylon.animation.js",
                 "../../src/Animations/babylon.animationGroup.js",
                 "../../src/Animations/babylon.runtimeAnimation.js",
@@ -660,7 +661,8 @@
                 "../../src/Gamepad/Controllers/babylon.viveController.js",
                 "../../src/Gamepad/Controllers/babylon.genericController.js",
                 "../../src/Gamepad/Controllers/babylon.windowsMotionController.js",
-                "../../src/Gamepad/Controllers/babylon.gearVRController.js"
+                "../../src/Gamepad/Controllers/babylon.gearVRController.js",
+                "../../src/Gamepad/Controllers/babylon.daydreamController.js"
             ],
             "dependUpon": [
                 "core"
@@ -822,6 +824,8 @@
                 "../../src/PostProcess/babylon.refractionPostProcess.js",
                 "../../src/PostProcess/babylon.blackAndWhitePostProcess.js",
                 "../../src/PostProcess/babylon.convolutionPostProcess.js",
+                "../../src/PostProcess/babylon.sharpenPostProcess.js",
+                "../../src/PostProcess/babylon.chromaticAberrationPostProcess.js",
                 "../../src/PostProcess/babylon.filterPostProcess.js",
                 "../../src/PostProcess/babylon.fxaaPostProcess.js",
                 "../../src/PostProcess/babylon.volumetricLightScatteringPostProcess.js",
@@ -838,6 +842,7 @@
                 "refraction.fragment",
                 "blackAndWhite.fragment",
                 "convolution.fragment",
+                "sharpen.fragment",
                 "filter.fragment",
                 "fxaa.fragment",
                 "volumetricLightScattering.fragment",
@@ -1315,7 +1320,10 @@
             "buildAsModule": true,
             "moduleName": "babylonjs-materials",
             "outputFilename": "babylonjs.materials",
-            "moduleDeclaration": "BJSMaterials",
+            "moduleDeclaration": {
+                "name": "BJSMaterials",
+                "module": "babylonjs-materials"
+            },
             "extendsRoot": true
         }
     },
@@ -1346,7 +1354,10 @@
             "buildAsModule": true,
             "moduleName": "babylonjs-post-process",
             "outputFilename": "babylonjs.postProcess",
-            "moduleDeclaration": "BJSPostProcess",
+            "moduleDeclaration": {
+                "name": "PostProcesses",
+                "module": "babylonjs-post-process"
+            },
             "extendsRoot": true
         }
     },
@@ -1449,7 +1460,10 @@
             "buildAsModule": true,
             "moduleName": "babylonjs-procedural-textures",
             "outputFilename": "babylonjs.proceduralTextures",
-            "moduleDeclaration": "BJSProceduralTextures",
+            "moduleDeclaration": {
+                "name": "ProceduralTextures",
+                "module": "babylonjs-procedural-textures"
+            },
             "extendsRoot": true
         }
     },
@@ -1522,7 +1536,14 @@
             "buildAsModule": true,
             "moduleName": "babylonjs-loaders",
             "outputFilename": "babylonjs.loaders",
-            "moduleDeclaration": "BJSLoaders",
+            "moduleDeclaration": {
+                "name": "Loaders",
+                "module": "babylonjs-loaders"
+            },
+            "extraTypesDependencies": [
+                "babylonjs",
+                "babylonjs-gltf2interface"
+            ],
             "extendsRoot": true
         }
     },
@@ -1549,11 +1570,15 @@
             "distOutputDirectory": "/serializers/",
             "buildAsModule": true,
             "moduleName": "babylonjs-serializers",
-            "extraDeclarations": [
-                "../../dist/babylon.glTF2Interface.d.ts"
+            "extraTypesDependencies": [
+                "babylonjs",
+                "babylonjs-gltf2interface"
             ],
             "outputFilename": "babylonjs.serializers",
-            "moduleDeclaration": "BJSSerializers",
+            "moduleDeclaration": {
+                "name": "Serializers",
+                "module": "babylonjs-serializers"
+            },
             "extendsRoot": true
         }
     },
@@ -1584,7 +1609,10 @@
                 "output": "babylon.gui.js",
                 "buildAsModule": true,
                 "moduleName": "babylonjs-gui",
-                "moduleDeclaration": "GUI"
+                "moduleDeclaration": {
+                    "name": "GUI",
+                    "module": "babylonjs-gui"
+                }
             }
         ],
         "build": {
@@ -1660,7 +1688,11 @@
                 "output": "babylon.inspector.js",
                 "webpack": "../../inspector/webpack.config.js",
                 "bundle": "true",
-                "moduleDeclaration": "INSPECTOR"
+                "moduleDeclaration": {
+                    "name": "INSPECTOR",
+                    "module": "babylonjs-inspector"
+                },
+                "extendsRoot": true
             }
         ],
         "build": {
@@ -1676,7 +1708,10 @@
                 "output": "babylon.viewer.js",
                 "webpack": "../../Viewer/webpack.gulp.config.js",
                 "bundle": "true",
-                "moduleDeclaration": "BabylonViewer",
+                "moduleDeclaration": {
+                    "name": "BabylonViewer",
+                    "module": "babylonjs-viewer"
+                },
                 "babylonIncluded": true
             }
         ],

+ 4 - 3
Tools/Gulp/gulp-addDtsExport.js

@@ -6,7 +6,7 @@ module.exports = function (varName, moduleName, subModule, extendsRoot, dependen
 
         let exportText = "BABYLON";
         if (subModule && !extendsRoot) {
-            exportText += '.' + varName;
+            exportText += '.' + varName.name;
         }
 
         let referenceText = '';
@@ -17,8 +17,9 @@ module.exports = function (varName, moduleName, subModule, extendsRoot, dependen
         if (dependencies) {
             referenceText = '';
             dependencies.forEach(element => {
-                referenceText += `/// <reference types="babylonjs/${element}"/>
-`
+                // was "babylonjs/${element}""
+                referenceText += `/// <reference types="${element}"/>
+`;
             });
         }
 

+ 23 - 29
Tools/Gulp/gulp-addModuleExports.js

@@ -7,39 +7,36 @@ var through = require('through2');
  */
 module.exports = function (varName, subModule, extendsRoot, externalUsingBabylon, noBabylonInit) {
     return through.obj(function (file, enc, cb) {
+        if (typeof varName === 'string') {
+            varName = {
+                name: varName,
+                module: varName
+            }
+            if (varName.name === 'BABYLON') {
+                varName.module = 'babylonjs';
+            }
+        }
 
-        var optionalRequire = `var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-var babylonDependency = (globalObject && globalObject.BABYLON) || BABYLON || (typeof require !== 'undefined' && require("babylonjs"));
-var BABYLON = babylonDependency;
-`;
         function moduleExportAddition(varName) {
 
-            let base = subModule ? 'BABYLON' : varName;
-
-            let basicInit = `root["${base}"]${(subModule && !extendsRoot) ? '["' + varName + '"]' : ''} = f;`;
-            let sadGlobalPolution = (!subModule) ? `var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-globalObject["${base}"] = f;` : '';
-            /*if (extendsRoot) {
-                basicInit = `__extends(root["BABYLON"], factory()); `
-            }*/
+            let base = subModule ? 'BABYLON' : varName.name;
 
             return `\n\n(function universalModuleDefinition(root, factory) {
-                var f = factory();
-                if (root && root["${base}"]) {
-                    return;
-                }
-                ${sadGlobalPolution}
     if(typeof exports === 'object' && typeof module === 'object')
-        module.exports = f;
+        module.exports = factory(${subModule || extendsRoot ? 'require("babylonjs")' : ''});
     else if(typeof define === 'function' && define.amd)
-        define(["${varName}"], factory);
+        define("${varName.module}", ${subModule || extendsRoot ? '["babylonjs"],' : ''} factory);
     else if(typeof exports === 'object')
-        exports["${varName}"] = f;
+        exports["${varName.module}"] = factory(${subModule || extendsRoot ? 'require("babylonjs")' : ''});
     else {
-        ${basicInit}
+        root["${base}"]${(subModule && !extendsRoot) ? '["' + varName.name + '"]' : ''} = factory(root["BABYLON"]);
     }
-})(this, function() {
-    return ${base}${(subModule && !extendsRoot) ? '.' + varName : ''};
+})(this, function(${varName.name === 'BABYLON' || noBabylonInit ? '' : 'BABYLON'}) {
+    ${String(file.contents)}
+    ${varName.name === 'BABYLON' || varName.name === 'INSPECTOR' ? `
+var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
+globalObject["${varName.name}"] = ${varName.name}` : ''}
+    return ${base}${(subModule && !extendsRoot) ? '.' + varName.name : ''};
 });
 `;
         }
@@ -75,17 +72,14 @@ globalObject["${base}"] = f;` : '';
             return;
         }
 
-        if (noBabylonInit) {
-            optionalRequire = '';
-        }
+        var optionalRequire = '';
 
         try {
             if (externalUsingBabylon) {
-                //file.contents = new Buffer(optionalRequire.concat(String(file.contents)));
-                file.contents = new Buffer(optionalRequire.concat(new Buffer(String(file.contents).concat(moduleExportAddition(varName)))));
+                file.contents = new Buffer(optionalRequire.concat(new Buffer(String('').concat(moduleExportAddition(varName)))));
             } else {
                 let pretext = subModule ? optionalRequire : '';
-                file.contents = new Buffer(pretext.concat(decorateAddition).concat(new Buffer(extendsAddition.concat(String(file.contents)).concat(moduleExportAddition(varName)))));
+                file.contents = new Buffer(pretext.concat(decorateAddition).concat(new Buffer(extendsAddition.concat(String('')).concat(moduleExportAddition(varName)))));
             }
             this.push(file);
         } catch (err) {

+ 3 - 6
Tools/Gulp/gulpfile.js

@@ -325,13 +325,10 @@ var buildExternalLibraries = function (settings) {
             let dtsFiles = files.map(function (filename) {
                 return filename.replace(".js", ".d.ts");
             });
-            if (settings.build.extraDeclarations) {
-                settings.build.extraDeclarations.forEach(file => { dtsFiles.unshift(file) })
-            }
             let dtsTask = gulp.src(dtsFiles)
                 .pipe(concat(settings.build.outputFilename + ".module.d.ts"))
                 .pipe(replace(referenceSearchRegex, ""))
-                .pipe(addDtsExport(settings.build.moduleDeclaration, settings.build.moduleName, true, settings.build.extendsRoot))
+                .pipe(addDtsExport(settings.build.moduleDeclaration, settings.build.moduleName, true, settings.build.extendsRoot, settings.build.extraTypesDependencies))
                 .pipe(gulp.dest(outputDirectory));
 
             return merge2([srcTask, dtsTask]);
@@ -421,7 +418,7 @@ var buildExternalLibrary = function (library, settings, watch) {
             var dts2 = tsProcess.dts
                 .pipe(concat(library.output))
                 .pipe(replace(referenceSearchRegex, ""))
-                .pipe(addDtsExport(library.moduleDeclaration, library.moduleName, true, library.extendsRoot))
+                .pipe(addDtsExport(library.moduleDeclaration, library.moduleName, true, library.extendsRoot, config.build.extraTypesDependencies))
                 .pipe(rename({ extname: ".module.d.ts" }))
                 .pipe(gulp.dest(outputDirectory));
             waitAll = merge2([dev, code, css, dts, dts2]);
@@ -483,7 +480,7 @@ var buildExternalLibrary = function (library, settings, watch) {
                 sequence.push(
                     wpBuild
                         .pipe(rename(library.output.replace(".js", library.noBundleInName ? '.js' : ".bundle.js")))
-                        .pipe(addModuleExports(library.moduleDeclaration, false, false, true))
+                        .pipe(addModuleExports(library.moduleDeclaration, false, library.extendsRoot, true))
                         .pipe(uglify())
                         .pipe(optimisejs())
                         .pipe(gulp.dest(outputDirectory))

+ 7 - 7
Tools/Gulp/package.json

@@ -9,21 +9,21 @@
     "readme": "https://github.com/BabylonJS/Babylon.js/edit/master/readme.md",
     "license": "(Apache-2.0)",
     "devDependencies": {
-        "@types/node": "^8.5.0",
+        "@types/node": "^8.9.4",
         "base64-image-loader": "^1.2.1",
         "chai": "^4.1.2",
         "color-support": "^1.1.3",
         "css-loader": "^0.25.0",
         "deepmerge": "^2.0.1",
         "del": "2.2.2",
-        "es6-promise": "^4.1.1",
+        "es6-promise": "^4.2.4",
         "exports-loader": "^0.6.4",
         "gulp": "^3.8.11",
         "gulp-changed-in-place": "2.0.3",
         "gulp-clean-ts-extends": "~0.1.1",
         "gulp-concat": "~2.5.2",
         "gulp-content-to-variable": "^0.1.0",
-        "gulp-debug": "^3.0.0",
+        "gulp-debug": "^3.2.0",
         "gulp-expect-file": "^0.0.7",
         "gulp-optimize-js": "^1.0.2",
         "gulp-rename": "~1.2.2",
@@ -31,12 +31,12 @@
         "gulp-sass": "3.1.0",
         "gulp-sourcemaps": "~1.9.1",
         "gulp-typedoc": "^2.1.2",
-        "gulp-typescript": "^3.2.3",
+        "gulp-typescript": "^3.2.4",
         "gulp-uglify": "^2.1.2",
         "gulp-util": "~3.0.4",
         "gulp-webserver": "^0.9.1",
         "handlebars": "^4.0.11",
-        "html-loader": "^0.5.1",
+        "html-loader": "^0.5.5",
         "imports-loader": "^0.7.1",
         "json-loader": "^0.5.7",
         "karma": "^2.0.0",
@@ -52,13 +52,13 @@
         "mocha": "^4.0.1",
         "phantomjs": "^2.1.7",
         "run-sequence": "~1.1.0",
-        "sinon": "^4.1.3",
+        "sinon": "^4.3.0",
         "style-loader": "^0.13.2",
         "through2": "~0.6.5",
         "ts-loader": "^2.3.7",
         "typedoc": "^0.9.0",
         "typescript": "~2.6.2",
-        "webpack-stream": "^4.0.0"
+        "webpack-stream": "^4.0.1"
     },
     "scripts": {
         "install": "npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && gulp deployLocalDev"

+ 5 - 5
Tools/Gulp/readme.md

@@ -66,11 +66,11 @@ gulp run
 ```
 
 you can now freely test in the following URLs:
-- [Playground]("http://localhost:1338/Playground/index-local.html")
-- [Materials Library]("http://localhost:1338/materialsLibrary/index.html")
-- [Postprocess Library]("http://localhost:1338/postProcessLibrary/index.html")
-- [Procedural Textures Library]("http://localhost:1338/proceduralTexturesLibrary/index.html")
-- [Local Dev Samples]("http://localhost:1338/localDev/index.html")
+- [Playground](http://localhost:1338/Playground/index-local.html)
+- [Materials Library](http://localhost:1338/materialsLibrary/index.html)
+- [Postprocess Library](http://localhost:1338/postProcessLibrary/index.html)
+- [Procedural Textures Library](http://localhost:1338/proceduralTexturesLibrary/index.html)
+- [Local Dev Samples](http://localhost:1338/localDev/index.html)
 
 ### Compile all the typscript files to their javascript respective files including declaration file
 ```

+ 14 - 1
Tools/Publisher/index.js

@@ -25,6 +25,10 @@ let packages = [
         path: basePath + '/postProcessesLibrary/'
     },
     {
+        name: 'gltf2interface',
+        path: basePath + '/gltf2interface/'
+    },
+    {
         name: 'loaders',
         path: basePath + '/loaders/'
     },
@@ -70,6 +74,13 @@ function processPackages(version) {
         } else {
             let packageJson = require(package.path + 'package.json');
             packageJson.version = version;
+            if (packageJson.dependencies) {
+                Object.keys(packageJson.dependencies).forEach(key => {
+                    if (key.indexOf("babylonjs") !== -1) {
+                        packageJson.dependencies[key] = version;
+                    }
+                });
+            }
             if (packageJson.peerDependencies) packageJson.peerDependencies.babylonjs = minimumDependency;
             fs.writeFileSync(package.path + 'package.json', JSON.stringify(packageJson, null, 4));
             console.log('Publishing ' + package.name + " from " + package.path);
@@ -89,7 +100,9 @@ if (loginCheck.code === 0) {
     prompt.get(['version'], function (err, result) {
         let version = result.version;
         updateEngineVersion(version);
-        runGulp();
+        if (process.argv.indexOf('--no-build') === -1) {
+            runGulp();
+        }
         processPackages(version);
 
         console.log("done, please tag git with " + version);

+ 1 - 1
Viewer/src/configuration/configuration.ts

@@ -257,5 +257,5 @@ export interface IImageProcessingConfiguration {
     vignetteBlendMode?: number;
     vignetteM?: boolean;
     applyByPostProcess?: boolean;
-
+    isEnabled?: boolean;
 }

+ 6 - 2
Viewer/src/templateManager.ts

@@ -125,6 +125,7 @@ export class TemplateManager {
             let templateStructure = {};
             // now iterate through all templates and check for children:
             let buildTree = (parentObject, name) => {
+                this.templates[name].isInHtmlTree = true;
                 let childNodes = this.templates[name].getChildElements().filter(n => !!this.templates[n]);
                 childNodes.forEach(element => {
                     parentObject[element] = {};
@@ -149,7 +150,7 @@ export class TemplateManager {
 
     private checkLoadedState() {
         let done = Object.keys(this.templates).length === 0 || Object.keys(this.templates).every((key) => {
-            return this.templates[key].isLoaded && !!this.templates[key].parent;
+            return (this.templates[key].isLoaded && !!this.templates[key].parent) || !this.templates[key].isInHtmlTree;
         });
 
         if (done) {
@@ -205,6 +206,8 @@ export class Template {
      */
     public isShown: boolean;
 
+    public isInHtmlTree: boolean;
+
     public parent: HTMLElement;
 
     public initPromise: Promise<Template>;
@@ -225,6 +228,7 @@ export class Template {
 
         this.isLoaded = false;
         this.isShown = false;
+        this.isInHtmlTree = false;
         /*
         if (configuration.id) {
             this.parent.id = configuration.id;
@@ -361,7 +365,7 @@ export class Template {
     private getTemplateAsHtml(templateConfig: ITemplateConfiguration): Promise<string> {
         if (!templateConfig) {
             return Promise.reject('No templateConfig provided');
-        } else if (templateConfig.html) {
+        } else if (templateConfig.html !== undefined) {
             return Promise.resolve(templateConfig.html);
         } else {
             let location = getTemplateLocation(templateConfig);

+ 4 - 5
Viewer/src/viewer/defaultViewer.ts

@@ -260,7 +260,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public showOverlayScreen(subScreen: string) {
         let template = this.templateManager.getTemplate('overlay');
-        if (!template) return Promise.reject('Overlay template not found');
+        if (!template) return Promise.resolve('Overlay template not found');
 
         return template.show((template => {
 
@@ -285,7 +285,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public hideOverlayScreen() {
         let template = this.templateManager.getTemplate('overlay');
-        if (!template) return Promise.reject('Overlay template not found');
+        if (!template) return Promise.resolve('Overlay template not found');
 
         return template.hide((template => {
             template.parent.style.opacity = "0";
@@ -313,7 +313,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public showLoadingScreen() {
         let template = this.templateManager.getTemplate('loadingScreen');
-        if (!template) return Promise.reject('oading Screen template not found');
+        if (!template) return Promise.resolve('Loading Screen template not found');
 
         return template.show((template => {
 
@@ -332,7 +332,7 @@ export class DefaultViewer extends AbstractViewer {
 
     public hideLoadingScreen() {
         let template = this.templateManager.getTemplate('loadingScreen');
-        if (!template) return Promise.reject('oading Screen template not found');
+        if (!template) return Promise.resolve('Loading Screen template not found');
 
         return template.hide((template => {
             template.parent.style.opacity = "0";
@@ -347,7 +347,6 @@ export class DefaultViewer extends AbstractViewer {
 
     protected configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean } = {}, focusMeshes: Array<AbstractMesh> = this.scene.meshes) {
         super.configureLights(lightsConfiguration, focusMeshes);
-        console.log("flashlight", this.configuration.lab);
         // labs feature - flashlight
         if (this.configuration.lab && this.configuration.lab.flashlight) {
             let pointerPosition = BABYLON.Vector3.Zero();

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

@@ -600,10 +600,8 @@ export abstract class AbstractViewer {
 
             if (unitSize) {
                 meshesToNormalize.forEach(mesh => {
-                    console.log(mesh.scaling.x)
                     mesh.normalizeToUnitCube(true);
                     mesh.computeWorldMatrix(true);
-                    console.log(mesh.scaling.x)
                 });
             }
             if (center) {

File diff suppressed because it is too large
+ 12345 - 12008
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 57 - 57
dist/preview release/babylon.js


File diff suppressed because it is too large
+ 956 - 135
dist/preview release/babylon.max.js


File diff suppressed because it is too large
+ 58 - 58
dist/preview release/babylon.worker.js


File diff suppressed because it is too large
+ 8084 - 7747
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


File diff suppressed because it is too large
+ 60 - 59
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


File diff suppressed because it is too large
+ 956 - 141
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


File diff suppressed because it is too large
+ 941 - 124
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js


File diff suppressed because it is too large
+ 941 - 118
dist/preview release/es6.js


+ 248 - 0
dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts

@@ -0,0 +1,248 @@
+declare module BABYLON.GLTF2 {
+    const enum AccessorComponentType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+    }
+    const enum AccessorType {
+        SCALAR = "SCALAR",
+        VEC2 = "VEC2",
+        VEC3 = "VEC3",
+        VEC4 = "VEC4",
+        MAT2 = "MAT2",
+        MAT3 = "MAT3",
+        MAT4 = "MAT4",
+    }
+    const enum AnimationChannelTargetPath {
+        TRANSLATION = "translation",
+        ROTATION = "rotation",
+        SCALE = "scale",
+        WEIGHTS = "weights",
+    }
+    const enum AnimationSamplerInterpolation {
+        LINEAR = "LINEAR",
+        STEP = "STEP",
+        CUBICSPLINE = "CUBICSPLINE",
+    }
+    const enum CameraType {
+        PERSPECTIVE = "perspective",
+        ORTHOGRAPHIC = "orthographic",
+    }
+    const enum ImageMimeType {
+        JPEG = "image/jpeg",
+        PNG = "image/png",
+    }
+    const enum MaterialAlphaMode {
+        OPAQUE = "OPAQUE",
+        MASK = "MASK",
+        BLEND = "BLEND",
+    }
+    const enum MeshPrimitiveMode {
+        POINTS = 0,
+        LINES = 1,
+        LINE_LOOP = 2,
+        LINE_STRIP = 3,
+        TRIANGLES = 4,
+        TRIANGLE_STRIP = 5,
+        TRIANGLE_FAN = 6,
+    }
+    const enum TextureMagFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+    }
+    const enum TextureMinFilter {
+        NEAREST = 9728,
+        LINEAR = 9729,
+        NEAREST_MIPMAP_NEAREST = 9984,
+        LINEAR_MIPMAP_NEAREST = 9985,
+        NEAREST_MIPMAP_LINEAR = 9986,
+        LINEAR_MIPMAP_LINEAR = 9987,
+    }
+    const enum TextureWrapMode {
+        CLAMP_TO_EDGE = 33071,
+        MIRRORED_REPEAT = 33648,
+        REPEAT = 10497,
+    }
+    interface IProperty {
+        extensions?: {
+            [key: string]: any;
+        };
+        extras?: any;
+    }
+    interface IChildRootProperty extends IProperty {
+        name?: string;
+    }
+    interface IAccessorSparseIndices extends IProperty {
+        bufferView: number;
+        byteOffset?: number;
+        componentType: AccessorComponentType;
+    }
+    interface IAccessorSparseValues extends IProperty {
+        bufferView: number;
+        byteOffset?: number;
+    }
+    interface IAccessorSparse extends IProperty {
+        count: number;
+        indices: IAccessorSparseIndices;
+        values: IAccessorSparseValues;
+    }
+    interface IAccessor extends IChildRootProperty {
+        bufferView?: number;
+        byteOffset?: number;
+        componentType: AccessorComponentType;
+        normalized?: boolean;
+        count: number;
+        type: AccessorType;
+        max?: number[];
+        min?: number[];
+        sparse?: IAccessorSparse;
+    }
+    interface IAnimationChannel extends IProperty {
+        sampler: number;
+        target: IAnimationChannelTarget;
+    }
+    interface IAnimationChannelTarget extends IProperty {
+        node: number;
+        path: AnimationChannelTargetPath;
+    }
+    interface IAnimationSampler extends IProperty {
+        input: number;
+        interpolation?: AnimationSamplerInterpolation;
+        output: number;
+    }
+    interface IAnimation extends IChildRootProperty {
+        channels: IAnimationChannel[];
+        samplers: IAnimationSampler[];
+    }
+    interface IAsset extends IChildRootProperty {
+        copyright?: string;
+        generator?: string;
+        version: string;
+        minVersion?: string;
+    }
+    interface IBuffer extends IChildRootProperty {
+        uri?: string;
+        byteLength: number;
+    }
+    interface IBufferView extends IChildRootProperty {
+        buffer: number;
+        byteOffset?: number;
+        byteLength: number;
+        byteStride?: number;
+    }
+    interface ICameraOrthographic extends IProperty {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+    interface ICameraPerspective extends IProperty {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+    interface ICamera extends IChildRootProperty {
+        orthographic?: ICameraOrthographic;
+        perspective?: ICameraPerspective;
+        type: CameraType;
+    }
+    interface IImage extends IChildRootProperty {
+        uri?: string;
+        mimeType?: ImageMimeType;
+        bufferView?: number;
+    }
+    interface IMaterialNormalTextureInfo extends ITextureInfo {
+        scale?: number;
+    }
+    interface IMaterialOcclusionTextureInfo extends ITextureInfo {
+        strength?: number;
+    }
+    interface IMaterialPbrMetallicRoughness {
+        baseColorFactor?: number[];
+        baseColorTexture?: ITextureInfo;
+        metallicFactor?: number;
+        roughnessFactor?: number;
+        metallicRoughnessTexture?: ITextureInfo;
+    }
+    interface IMaterial extends IChildRootProperty {
+        pbrMetallicRoughness?: IMaterialPbrMetallicRoughness;
+        normalTexture?: IMaterialNormalTextureInfo;
+        occlusionTexture?: IMaterialOcclusionTextureInfo;
+        emissiveTexture?: ITextureInfo;
+        emissiveFactor?: number[];
+        alphaMode?: MaterialAlphaMode;
+        alphaCutoff?: number;
+        doubleSided?: boolean;
+    }
+    interface IMeshPrimitive extends IProperty {
+        attributes: {
+            [name: string]: number;
+        };
+        indices?: number;
+        material?: number;
+        mode?: MeshPrimitiveMode;
+        targets?: {
+            [name: string]: number;
+        }[];
+    }
+    interface IMesh extends IChildRootProperty {
+        primitives: IMeshPrimitive[];
+        weights?: number[];
+    }
+    interface INode extends IChildRootProperty {
+        camera?: number;
+        children?: number[];
+        skin?: number;
+        matrix?: number[];
+        mesh?: number;
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+        weights?: number[];
+    }
+    interface ISampler extends IChildRootProperty {
+        magFilter?: TextureMagFilter;
+        minFilter?: TextureMinFilter;
+        wrapS?: TextureWrapMode;
+        wrapT?: TextureWrapMode;
+    }
+    interface IScene extends IChildRootProperty {
+        nodes: number[];
+    }
+    interface ISkin extends IChildRootProperty {
+        inverseBindMatrices?: number;
+        skeleton?: number;
+        joints: number[];
+    }
+    interface ITexture extends IChildRootProperty {
+        sampler?: number;
+        source: number;
+    }
+    interface ITextureInfo {
+        index: number;
+        texCoord?: number;
+    }
+    interface IGLTF extends IProperty {
+        accessors?: IAccessor[];
+        animations?: IAnimation[];
+        asset: IAsset;
+        buffers?: IBuffer[];
+        bufferViews?: IBufferView[];
+        cameras?: ICamera[];
+        extensionsUsed?: string[];
+        extensionsRequired?: string[];
+        images?: IImage[];
+        materials?: IMaterial[];
+        meshes?: IMesh[];
+        nodes?: INode[];
+        samplers?: ISampler[];
+        scene?: number;
+        scenes?: IScene[];
+        skins?: ISkin[];
+        textures?: ITexture[];
+    }
+}

+ 28 - 0
dist/preview release/gltf2Interface/package.json

@@ -0,0 +1,28 @@
+{
+    "name": "babylonjs-gltf2interface",
+    "description": "A typescript declaration of babylon's gltf2 inteface.",
+    "version": "3.2.0-alphaB",
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/BabylonJS/Babylon.js.git"
+    },
+    "files": [
+        "babylon.glTF2Interface.d.ts",
+        "package.json"
+    ],
+    "typings": "babylon.glTF2Interface.d.ts",
+    "keywords": [
+        "3D",
+        "javascript",
+        "html5",
+        "webgl",
+        "gltf2"
+    ],
+    "license": "Apache-2.0",
+    "peerDependencies": {
+        "babylonjs": ">=3.2.0-alpha"
+    },
+    "engines": {
+        "node": "*"
+    }
+}

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

@@ -32,6 +32,7 @@ declare module BABYLON.GUI {
         private _fullscreenViewport;
         private _idealWidth;
         private _idealHeight;
+        private _useSmallestIdeal;
         private _renderAtIdealSize;
         private _focusedControl;
         private _blockNextFocusCheck;
@@ -40,6 +41,7 @@ declare module BABYLON.GUI {
         background: string;
         idealWidth: number;
         idealHeight: number;
+        useSmallestIdeal: boolean;
         renderAtIdealSize: boolean;
         readonly layer: Nullable<Layer>;
         readonly rootContainer: Container;
@@ -185,6 +187,7 @@ declare module BABYLON.GUI {
         private _transformMatrix;
         protected _invertTransformMatrix: Matrix2D;
         protected _transformedPosition: Vector2;
+        private _onlyMeasureMode;
         private _isMatrixDirty;
         private _cachedOffsetX;
         private _cachedOffsetY;
@@ -227,6 +230,11 @@ declare module BABYLON.GUI {
         */
         onPointerUpObservable: Observable<Vector2WithInfo>;
         /**
+        * An event triggered when a control is clicked on
+        * @type {BABYLON.Observable}
+        */
+        onPointerClickObservable: Observable<Vector2WithInfo>;
+        /**
         * An event triggered when pointer enters the control
         * @type {BABYLON.Observable}
         */
@@ -311,7 +319,7 @@ declare module BABYLON.GUI {
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         forcePointerUp(pointerId?: Nullable<number>): void;
         _processObservables(type: number, x: number, y: number, pointerId: number, buttonIndex: number): boolean;
         private _prepareFont();
@@ -496,7 +504,7 @@ declare module BABYLON.GUI {
         private _updateValueFromPointer(x, y);
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
     }
 }
 
@@ -710,7 +718,7 @@ declare module BABYLON.GUI {
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
         static CreateImageOnlyButton(name: string, imageUrl: string): Button;
         static CreateSimpleButton(name: string, text: string): Button;
@@ -753,7 +761,7 @@ declare module BABYLON.GUI {
         private _isPointOnWheel(coordinates);
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
     }
 }
 
@@ -801,7 +809,7 @@ declare module BABYLON.GUI {
         processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         dispose(): void;
     }
 }

+ 96 - 41
dist/preview release/gui/babylon.gui.js

@@ -1,6 +1,3 @@
-var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-var babylonDependency = (globalObject && globalObject.BABYLON) || BABYLON || (typeof require !== 'undefined' && require("babylonjs"));
-var BABYLON = babylonDependency;
 var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -17,7 +14,20 @@ var __extends = (this && this.__extends) || (function () {
                 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
             };
         })();
-        /// <reference path="../../dist/preview release/babylon.d.ts"/>
+        
+
+(function universalModuleDefinition(root, factory) {
+    if(typeof exports === 'object' && typeof module === 'object')
+        module.exports = factory(require("babylonjs"));
+    else if(typeof define === 'function' && define.amd)
+        define("babylonjs-gui", ["babylonjs"], factory);
+    else if(typeof exports === 'object')
+        exports["babylonjs-gui"] = factory(require("babylonjs"));
+    else {
+        root["BABYLON"]["GUI"] = factory(root["BABYLON"]);
+    }
+})(this, function(BABYLON) {
+    /// <reference path="../../dist/preview release/babylon.d.ts"/>
 
 var BABYLON;
 (function (BABYLON) {
@@ -41,6 +51,7 @@ var BABYLON;
                 _this._fullscreenViewport = new BABYLON.Viewport(0, 0, 1, 1);
                 _this._idealWidth = 0;
                 _this._idealHeight = 0;
+                _this._useSmallestIdeal = false;
                 _this._renderAtIdealSize = false;
                 _this._blockNextFocusCheck = false;
                 _this._renderScale = 1;
@@ -125,6 +136,21 @@ var BABYLON;
                 enumerable: true,
                 configurable: true
             });
+            Object.defineProperty(AdvancedDynamicTexture.prototype, "useSmallestIdeal", {
+                get: function () {
+                    return this._useSmallestIdeal;
+                },
+                set: function (value) {
+                    if (this._useSmallestIdeal === value) {
+                        return;
+                    }
+                    this._useSmallestIdeal = value;
+                    this.markAsDirty();
+                    this._rootContainer._markAllAsDirty();
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(AdvancedDynamicTexture.prototype, "renderAtIdealSize", {
                 get: function () {
                     return this._renderAtIdealSize;
@@ -351,8 +377,8 @@ var BABYLON;
                 var engine = scene.getEngine();
                 var textureSize = this.getSize();
                 if (this._isFullscreen) {
-                    x = x * ((textureSize.width / this._renderScale) / engine.getRenderWidth());
-                    y = y * ((textureSize.height / this._renderScale) / engine.getRenderHeight());
+                    x = x * (textureSize.width / engine.getRenderWidth());
+                    y = y * (textureSize.height / engine.getRenderHeight());
                 }
                 if (this._capturingControl[pointerId]) {
                     this._capturingControl[pointerId]._processObservables(type, x, y, pointerId, buttonIndex);
@@ -739,11 +765,22 @@ var BABYLON;
             };
             ValueAndUnit.prototype.getValue = function (host) {
                 if (host && !this.ignoreAdaptiveScaling && this.unit !== ValueAndUnit.UNITMODE_PERCENTAGE) {
+                    var width = 0;
+                    var height = 0;
                     if (host.idealWidth) {
-                        return (this._value * host.getSize().width) / host.idealWidth;
+                        width = (this._value * host.getSize().width) / host.idealWidth;
                     }
                     if (host.idealHeight) {
-                        return (this._value * host.getSize().height) / host.idealHeight;
+                        height = (this._value * host.getSize().height) / host.idealHeight;
+                    }
+                    if (host.useSmallestIdeal && host.idealWidth && host.idealHeight) {
+                        return window.innerWidth < window.innerHeight ? width : height;
+                    }
+                    if (host.idealWidth) {
+                        return width;
+                    }
+                    if (host.idealHeight) {
+                        return height;
                     }
                 }
                 return this._value;
@@ -851,6 +888,7 @@ var BABYLON;
                 this._transformMatrix = GUI.Matrix2D.Identity();
                 this._invertTransformMatrix = GUI.Matrix2D.Identity();
                 this._transformedPosition = BABYLON.Vector2.Zero();
+                this._onlyMeasureMode = false;
                 this._isMatrixDirty = true;
                 this._isVisible = true;
                 this._fontSet = false;
@@ -889,6 +927,11 @@ var BABYLON;
                 */
                 this.onPointerUpObservable = new BABYLON.Observable();
                 /**
+                * An event triggered when a control is clicked on
+                * @type {BABYLON.Observable}
+                */
+                this.onPointerClickObservable = new BABYLON.Observable();
+                /**
                 * An event triggered when pointer enters the control
                 * @type {BABYLON.Observable}
                 */
@@ -1408,7 +1451,9 @@ var BABYLON;
             };
             Control.prototype.linkWithMesh = function (mesh) {
                 if (!this._host || this._root && this._root !== this._host._rootContainer) {
-                    BABYLON.Tools.Error("Cannot link a control to a mesh if the control is not at root level");
+                    if (mesh) {
+                        BABYLON.Tools.Error("Cannot link a control to a mesh if the control is not at root level");
+                    }
                     return;
                 }
                 var index = this._host._linkedControls.indexOf(this);
@@ -1419,14 +1464,30 @@ var BABYLON;
                     }
                     return;
                 }
+                else if (!mesh) {
+                    return;
+                }
                 this.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
                 this.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
                 this._linkedMesh = mesh;
+                this._onlyMeasureMode = true;
                 this._host._linkedControls.push(this);
             };
             Control.prototype._moveToProjectedPosition = function (projectedPosition) {
-                this.left = ((projectedPosition.x + this._linkOffsetX.getValue(this._host)) - this._currentMeasure.width / 2) + "px";
-                this.top = ((projectedPosition.y + this._linkOffsetY.getValue(this._host)) - this._currentMeasure.height / 2) + "px";
+                var oldLeft = this._left.getValue(this._host);
+                var oldTop = this._top.getValue(this._host);
+                var newLeft = ((projectedPosition.x + this._linkOffsetX.getValue(this._host)) - this._currentMeasure.width / 2);
+                var newTop = ((projectedPosition.y + this._linkOffsetY.getValue(this._host)) - this._currentMeasure.height / 2);
+                if (this._left.ignoreAdaptiveScaling && this._top.ignoreAdaptiveScaling) {
+                    if (Math.abs(newLeft - oldLeft) < 0.5) {
+                        newLeft = oldLeft;
+                    }
+                    if (Math.abs(newTop - oldTop) < 0.5) {
+                        newTop = oldTop;
+                    }
+                }
+                this.left = newLeft + "px";
+                this.top = newTop + "px";
                 this._left.ignoreAdaptiveScaling = true;
                 this._top.ignoreAdaptiveScaling = true;
             };
@@ -1523,6 +1584,10 @@ var BABYLON;
                 }
                 // Transform
                 this._transform(context);
+                if (this._onlyMeasureMode) {
+                    this._onlyMeasureMode = false;
+                    return false; // We do not want rendering for this frame as they are measure dependant information that need to be gathered
+                }
                 // Clip
                 this._clip(context);
                 context.clip();
@@ -1706,21 +1771,25 @@ var BABYLON;
                     this.parent._onPointerDown(target, coordinates, pointerId, buttonIndex);
                 return true;
             };
-            Control.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
+            Control.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
                 this._downCount = 0;
                 delete this._downPointerIds[pointerId];
+                var canNotifyClick = notifyClick;
+                if (notifyClick && this._enterCount > 0) {
+                    canNotifyClick = this.onPointerClickObservable.notifyObservers(new GUI.Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
+                }
                 var canNotify = this.onPointerUpObservable.notifyObservers(new GUI.Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
                 if (canNotify && this.parent != null)
-                    this.parent._onPointerUp(target, coordinates, pointerId, buttonIndex);
+                    this.parent._onPointerUp(target, coordinates, pointerId, buttonIndex, canNotifyClick);
             };
             Control.prototype.forcePointerUp = function (pointerId) {
                 if (pointerId === void 0) { pointerId = null; }
                 if (pointerId !== null) {
-                    this._onPointerUp(this, BABYLON.Vector2.Zero(), pointerId, 0);
+                    this._onPointerUp(this, BABYLON.Vector2.Zero(), pointerId, 0, true);
                 }
                 else {
                     for (var key in this._downPointerIds) {
-                        this._onPointerUp(this, BABYLON.Vector2.Zero(), +key, 0);
+                        this._onPointerUp(this, BABYLON.Vector2.Zero(), +key, 0, true);
                     }
                 }
             };
@@ -1746,7 +1815,7 @@ var BABYLON;
                 }
                 if (type === BABYLON.PointerEventTypes.POINTERUP) {
                     if (this._host._lastControlDown[pointerId]) {
-                        this._host._lastControlDown[pointerId]._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
+                        this._host._lastControlDown[pointerId]._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex, true);
                     }
                     delete this._host._lastControlDown[pointerId];
                     return true;
@@ -1768,6 +1837,7 @@ var BABYLON;
                 this.onPointerMoveObservable.clear();
                 this.onPointerOutObservable.clear();
                 this.onPointerUpObservable.clear();
+                this.onPointerClickObservable.clear();
                 if (this._root) {
                     this._root.removeControl(this);
                     this._root = null;
@@ -1982,6 +2052,7 @@ var BABYLON;
                     this._children.splice(index, 1);
                     control.parent = null;
                 }
+                control.linkWithMesh(null);
                 this._markAsDirty();
                 return this;
             };
@@ -2963,10 +3034,10 @@ var BABYLON;
                 }
                 _super.prototype._onPointerMove.call(this, target, coordinates);
             };
-            Slider.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
+            Slider.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
                 this._pointerIsDown = false;
                 delete this._host._capturingControl[pointerId];
-                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex, notifyClick);
             };
             return Slider;
         }(GUI.Control));
@@ -3978,11 +4049,11 @@ var BABYLON;
                 }
                 return true;
             };
-            Button.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
+            Button.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
                 if (this.pointerUpAnimation) {
                     this.pointerUpAnimation();
                 }
-                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex, notifyClick);
             };
             // Statics
             Button.CreateImageButton = function (name, text, imageUrl) {
@@ -4387,10 +4458,10 @@ var BABYLON;
                 }
                 _super.prototype._onPointerMove.call(this, target, coordinates);
             };
-            ColorPicker.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
+            ColorPicker.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
                 this._pointerIsDown = false;
                 delete this._host._capturingControl[pointerId];
-                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex, notifyClick);
             };
             return ColorPicker;
         }(GUI.Control));
@@ -4826,8 +4897,8 @@ var BABYLON;
                 this._host.focusedControl = this;
                 return true;
             };
-            InputText.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex) {
-                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex);
+            InputText.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
+                _super.prototype._onPointerUp.call(this, target, coordinates, pointerId, buttonIndex, notifyClick);
             };
             InputText.prototype.dispose = function () {
                 _super.prototype.dispose.call(this);
@@ -5002,22 +5073,6 @@ var BABYLON;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
 
-
-(function universalModuleDefinition(root, factory) {
-                var f = factory();
-                if (root && root["BABYLON"]) {
-                    return;
-                }
-                
-    if(typeof exports === 'object' && typeof module === 'object')
-        module.exports = f;
-    else if(typeof define === 'function' && define.amd)
-        define(["GUI"], factory);
-    else if(typeof exports === 'object')
-        exports["GUI"] = f;
-    else {
-        root["BABYLON"]["GUI"] = f;
-    }
-})(this, function() {
+    
     return BABYLON.GUI;
 });

File diff suppressed because it is too large
+ 4 - 3
dist/preview release/gui/babylon.gui.min.js


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

@@ -38,6 +38,7 @@ declare module BABYLON.GUI {
         private _fullscreenViewport;
         private _idealWidth;
         private _idealHeight;
+        private _useSmallestIdeal;
         private _renderAtIdealSize;
         private _focusedControl;
         private _blockNextFocusCheck;
@@ -46,6 +47,7 @@ declare module BABYLON.GUI {
         background: string;
         idealWidth: number;
         idealHeight: number;
+        useSmallestIdeal: boolean;
         renderAtIdealSize: boolean;
         readonly layer: Nullable<Layer>;
         readonly rootContainer: Container;
@@ -191,6 +193,7 @@ declare module BABYLON.GUI {
         private _transformMatrix;
         protected _invertTransformMatrix: Matrix2D;
         protected _transformedPosition: Vector2;
+        private _onlyMeasureMode;
         private _isMatrixDirty;
         private _cachedOffsetX;
         private _cachedOffsetY;
@@ -233,6 +236,11 @@ declare module BABYLON.GUI {
         */
         onPointerUpObservable: Observable<Vector2WithInfo>;
         /**
+        * An event triggered when a control is clicked on
+        * @type {BABYLON.Observable}
+        */
+        onPointerClickObservable: Observable<Vector2WithInfo>;
+        /**
         * An event triggered when pointer enters the control
         * @type {BABYLON.Observable}
         */
@@ -317,7 +325,7 @@ declare module BABYLON.GUI {
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         forcePointerUp(pointerId?: Nullable<number>): void;
         _processObservables(type: number, x: number, y: number, pointerId: number, buttonIndex: number): boolean;
         private _prepareFont();
@@ -502,7 +510,7 @@ declare module BABYLON.GUI {
         private _updateValueFromPointer(x, y);
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
     }
 }
 
@@ -716,7 +724,7 @@ declare module BABYLON.GUI {
         _onPointerEnter(target: Control): boolean;
         _onPointerOut(target: Control): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         static CreateImageButton(name: string, text: string, imageUrl: string): Button;
         static CreateImageOnlyButton(name: string, imageUrl: string): Button;
         static CreateSimpleButton(name: string, text: string): Button;
@@ -759,7 +767,7 @@ declare module BABYLON.GUI {
         private _isPointOnWheel(coordinates);
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         _onPointerMove(target: Control, coordinates: Vector2): void;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
     }
 }
 
@@ -807,7 +815,7 @@ declare module BABYLON.GUI {
         processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): void;
+        _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         dispose(): void;
     }
 }

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

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

File diff suppressed because it is too large
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


+ 21 - 2
dist/preview release/inspector/babylon.inspector.d.ts

@@ -420,13 +420,20 @@ declare module INSPECTOR {
         private _headerRow;
         private _detailRows;
         private _sortDirection;
+        private _searchDetails;
+        private _details;
         constructor(dr?: Array<PropertyLine>);
         details: Array<PropertyLine>;
         protected _build(): void;
         /** Updates the HTML of the detail panel */
-        update(): void;
+        update(_items?: Array<PropertyLine>): void;
+        /** Add the search bar for the details */
+        private _addSearchBarDetails();
+        /** Search an element by name  */
+        searchByName(searchName: string): void;
         /** Add all lines in the html div. Does not sort them! */
         private _addDetails();
+        private _addSearchDetails(_items);
         /**
          * Sort the details row by comparing the given property of each row
          */
@@ -435,6 +442,10 @@ declare module INSPECTOR {
          * Removes all data in the detail panel but keep the header row
          */
         clean(): void;
+        /**
+         * Clean the rows only
+         */
+        cleanRow(): void;
         /** Overrides basicelement.dispose */
         dispose(): void;
         /**
@@ -670,13 +681,21 @@ declare module INSPECTOR {
      * At each keypress on the input, the treepanel will be filtered.
      */
     class SearchBar extends BasicElement {
-        private _tab;
+        private _propTab;
         private _inputElement;
         constructor(tab: PropertyTab);
         /** Delete all characters typped in the input element */
         reset(): void;
         update(): void;
     }
+    class SearchBarDetails extends BasicElement {
+        private _detailTab;
+        private _inputElement;
+        constructor(tab: DetailPanel);
+        /** Delete all characters typped in the input element */
+        reset(): void;
+        update(): void;
+    }
 }
 
 declare module INSPECTOR {

+ 159 - 8
dist/preview release/inspector/babylon.inspector.js

@@ -1164,6 +1164,9 @@ var INSPECTOR;
         Object.defineProperty(DetailPanel.prototype, "details", {
             set: function (detailsRow) {
                 this.clean();
+                //add the searchBar
+                this._addSearchBarDetails();
+                this._details = INSPECTOR.Helpers.CreateDiv('details', this._div);
                 this._detailRows = detailsRow;
                 // Refresh HTML
                 this.update();
@@ -1179,16 +1182,49 @@ var INSPECTOR;
             this._div.appendChild(this._headerRow);
         };
         /** Updates the HTML of the detail panel */
-        DetailPanel.prototype.update = function () {
+        DetailPanel.prototype.update = function (_items) {
             this._sortDetails('name', 1);
-            this._addDetails();
+            // Check the searchbar
+            if (_items) {
+                this.cleanRow();
+                this._addSearchDetails(_items);
+                //console.log(_items);
+            }
+            else {
+                this._addDetails();
+                //console.log("np");
+            }
+        };
+        /** Add the search bar for the details */
+        DetailPanel.prototype._addSearchBarDetails = function () {
+            var searchDetails = INSPECTOR.Helpers.CreateDiv('searchbar-details', this._div);
+            // Create search bar
+            this._searchDetails = new INSPECTOR.SearchBarDetails(this);
+            searchDetails.appendChild(this._searchDetails.toHtml());
+            this._div.appendChild(searchDetails);
+        };
+        /** Search an element by name  */
+        DetailPanel.prototype.searchByName = function (searchName) {
+            var rows = [];
+            for (var _i = 0, _a = this._detailRows; _i < _a.length; _i++) {
+                var row = _a[_i];
+                if (row.name.indexOf(searchName) >= 0) {
+                    rows.push(row);
+                }
+            }
+            this.update(rows);
         };
         /** Add all lines in the html div. Does not sort them! */
         DetailPanel.prototype._addDetails = function () {
-            var details = INSPECTOR.Helpers.CreateDiv('details', this._div);
             for (var _i = 0, _a = this._detailRows; _i < _a.length; _i++) {
                 var row = _a[_i];
-                details.appendChild(row.toHtml());
+                this._details.appendChild(row.toHtml());
+            }
+        };
+        DetailPanel.prototype._addSearchDetails = function (_items) {
+            for (var _i = 0, _items_1 = _items; _i < _items_1.length; _i++) {
+                var row = _items_1[_i];
+                this._details.appendChild(row.toHtml());
             }
         };
         /**
@@ -1251,6 +1287,17 @@ var INSPECTOR;
             // Header row
             this._div.appendChild(this._headerRow);
         };
+        /**
+         * Clean the rows only
+         */
+        DetailPanel.prototype.cleanRow = function () {
+            // Delete all details row
+            for (var _i = 0, _a = this._detailRows; _i < _a.length; _i++) {
+                var pline = _a[_i];
+                pline.dispose();
+            }
+            INSPECTOR.Helpers.CleanDiv(this._details);
+        };
         /** Overrides basicelement.dispose */
         DetailPanel.prototype.dispose = function () {
             // Delete all details row
@@ -1630,6 +1677,57 @@ var INSPECTOR;
             }
             else {
                 this._valueDiv.childNodes[0].nodeValue = this._displayValueContent();
+                //Doing the Hexa convertion
+                if ((this._property.type == "Color3" && this._children.length == 5 && this._children[1].value == true) || (this._property.type == "Color4" && this._children.length == 6 && this._children[1].value == true)) {
+                    if (this._children[0] != undefined && this._children[0].name == "hex") {
+                        var hexLineString = this._children[0].value;
+                        var rValue = (parseInt((hexLineString.slice(1, 3)), 16)) * (1 / 255);
+                        var rValueRound = Math.round(100 * rValue) / 100;
+                        this.value.r = rValueRound;
+                        var gValue = (parseInt((hexLineString.slice(3, 5)), 16)) * (1 / 255);
+                        var gValueRound = Math.round(100 * gValue) / 100;
+                        this.value.g = gValueRound;
+                        var bValue = (parseInt((hexLineString.slice(5, 7)), 16)) * (1 / 255);
+                        var bValueRound = Math.round(100 * bValue) / 100;
+                        this.value.b = bValueRound;
+                        if (this._children[2].name == "a") {
+                            var aValue = (parseInt((hexLineString.slice(7, 9)), 16)) * (1 / 255);
+                            var aValueRound = Math.round(100 * aValue) / 100;
+                            this.value.a = aValueRound;
+                        }
+                    }
+                }
+                else if (this._property.type == "Color3" || this._property.type == "Color4") {
+                    if (this._property.value.hex != undefined && this._property.value.hex != null) {
+                        var hexLineInfos = [];
+                        var valHexR = ((this._property.value.r * 255) | 0).toString(16);
+                        hexLineInfos.push(valHexR);
+                        if (valHexR == "0") {
+                            hexLineInfos.push("0");
+                        }
+                        var valHexG = ((this._property.value.g * 255) | 0).toString(16);
+                        hexLineInfos.push(valHexG);
+                        if (valHexG == "0") {
+                            hexLineInfos.push("0");
+                        }
+                        var valHexB = ((this._property.value.b * 255) | 0).toString(16);
+                        hexLineInfos.push(valHexB);
+                        if (valHexB == "0") {
+                            hexLineInfos.push("0");
+                        }
+                        if (this._property.value.a != undefined) {
+                            var valHexA = ((this._property.value.a * 255) | 0).toString(16);
+                            hexLineInfos.push(valHexA);
+                            if (valHexA == "0") {
+                                hexLineInfos.push("0");
+                            }
+                        }
+                        hexLineInfos.unshift("#");
+                        var hexLineString = hexLineInfos.join("");
+                        this._property.value.hex = hexLineString;
+                        hexLineInfos.length = 0;
+                    }
+                }
             }
             for (var _i = 0, _a = this._elements; _i < _a.length; _i++) {
                 var elem = _a[_i];
@@ -1714,11 +1812,35 @@ var INSPECTOR;
                         var child = new PropertyLine(infos, this, this._level + PropertyLine._MARGIN_LEFT);
                         this._children.push(child);
                     }
+                    //Add the Hexa converter
+                    if ((propToDisplay.indexOf('r') && propToDisplay.indexOf('g') && propToDisplay.indexOf('b') && propToDisplay.indexOf('a')) == 0) {
+                        var hexLineInfos = [];
+                        var hexLinePropCheck = new INSPECTOR.Property("hexEnable", this._property.value);
+                        hexLinePropCheck.value = false;
+                        var hexLineCheck = new PropertyLine(hexLinePropCheck, this, this._level + PropertyLine._MARGIN_LEFT);
+                        this._children.unshift(hexLineCheck);
+                        for (var _c = 0, propToDisplay_2 = propToDisplay; _c < propToDisplay_2.length; _c++) {
+                            var prop = propToDisplay_2[_c];
+                            var infos = new INSPECTOR.Property(prop, this._property.value);
+                            var valHex = ((infos.value * 255) | 0).toString(16);
+                            hexLineInfos.push(valHex);
+                            if (valHex == "0") {
+                                hexLineInfos.push("0");
+                            }
+                        }
+                        hexLineInfos.push("#");
+                        hexLineInfos.reverse();
+                        var hexLineString = hexLineInfos.join("");
+                        var hexLineProp = new INSPECTOR.Property("hex", this._property.value);
+                        hexLineProp.value = hexLineString;
+                        var hexLine = new PropertyLine(hexLineProp, this, this._level + PropertyLine._MARGIN_LEFT);
+                        this._children.unshift(hexLine);
+                    }
                 }
                 // otherwise display it    
                 if (this._div.parentNode) {
-                    for (var _c = 0, _d = this._children; _c < _d.length; _c++) {
-                        var child = _d[_c];
+                    for (var _d = 0, _e = this._children; _d < _e.length; _d++) {
+                        var child = _e[_d];
                         this._div.parentNode.insertBefore(child.toHtml(), this._div.nextSibling);
                     }
                 }
@@ -2112,7 +2234,7 @@ var INSPECTOR;
         __extends(SearchBar, _super);
         function SearchBar(tab) {
             var _this = _super.call(this) || this;
-            _this._tab = tab;
+            _this._propTab = tab;
             _this._div.classList.add('searchbar');
             var filter = INSPECTOR.Inspector.DOCUMENT.createElement('i');
             filter.className = 'fa fa-search';
@@ -2123,7 +2245,7 @@ var INSPECTOR;
             _this._div.appendChild(_this._inputElement);
             _this._inputElement.addEventListener('keyup', function (evt) {
                 var filter = _this._inputElement.value;
-                _this._tab.filter(filter);
+                _this._propTab.filter(filter);
             });
             return _this;
         }
@@ -2137,6 +2259,35 @@ var INSPECTOR;
         return SearchBar;
     }(INSPECTOR.BasicElement));
     INSPECTOR.SearchBar = SearchBar;
+    var SearchBarDetails = /** @class */ (function (_super) {
+        __extends(SearchBarDetails, _super);
+        function SearchBarDetails(tab) {
+            var _this = _super.call(this) || this;
+            _this._detailTab = tab;
+            _this._div.classList.add('searchbar');
+            var filter = INSPECTOR.Inspector.DOCUMENT.createElement('i');
+            filter.className = 'fa fa-search';
+            _this._div.appendChild(filter);
+            // Create input
+            _this._inputElement = INSPECTOR.Inspector.DOCUMENT.createElement('input');
+            _this._inputElement.placeholder = 'Filter by name...';
+            _this._div.appendChild(_this._inputElement);
+            _this._inputElement.addEventListener('keyup', function (evt) {
+                var filter = _this._inputElement.value;
+                _this._detailTab.searchByName(filter);
+            });
+            return _this;
+        }
+        /** Delete all characters typped in the input element */
+        SearchBarDetails.prototype.reset = function () {
+            this._inputElement.value = '';
+        };
+        SearchBarDetails.prototype.update = function () {
+            // Nothing to update
+        };
+        return SearchBarDetails;
+    }(INSPECTOR.BasicElement));
+    INSPECTOR.SearchBarDetails = SearchBarDetails;
 })(INSPECTOR || (INSPECTOR = {}));
 
 var __extends = (this && this.__extends) || (function () {

File diff suppressed because it is too large
+ 4 - 4
dist/preview release/inspector/babylon.inspector.min.js


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

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

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 17 - 8
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -1074,8 +1074,9 @@ var BABYLON;
                     node._babylonMesh.scaling = BABYLON.Vector3.One();
                 };
                 if (skin._loaded) {
-                    assignSkeleton();
-                    return skin._loaded;
+                    return skin._loaded.then(function () {
+                        assignSkeleton();
+                    });
                 }
                 // TODO: split into two parts so that bones are created before inverseBindMatricesData is loaded (for compiling materials).
                 return (skin._loaded = this._loadSkinInverseBindMatricesDataAsync(context, skin).then(function (inverseBindMatricesData) {
@@ -1962,7 +1963,9 @@ var BABYLON;
                             var nodeLOD = nodeLODs[indexLOD];
                             if (indexLOD !== 0) {
                                 _this._loadingNodeLOD = nodeLOD;
-                                _this._loadNodeSignals[nodeLOD._index] = new BABYLON.Deferred();
+                                if (!_this._loadNodeSignals[nodeLOD._index]) {
+                                    _this._loadNodeSignals[nodeLOD._index] = new BABYLON.Deferred();
+                                }
                             }
                             var promise = _this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(function () {
                                 if (indexLOD !== 0) {
@@ -1971,8 +1974,10 @@ var BABYLON;
                                 }
                                 if (indexLOD !== nodeLODs.length - 1) {
                                     var nodeIndex = nodeLODs[indexLOD + 1]._index;
-                                    _this._loadNodeSignals[nodeIndex].resolve();
-                                    delete _this._loadNodeSignals[nodeIndex];
+                                    if (_this._loadNodeSignals[nodeIndex]) {
+                                        _this._loadNodeSignals[nodeIndex].resolve();
+                                        delete _this._loadNodeSignals[nodeIndex];
+                                    }
                                 }
                             });
                             if (indexLOD === 0) {
@@ -2002,13 +2007,17 @@ var BABYLON;
                             var materialLOD = materialLODs[indexLOD];
                             if (indexLOD !== 0) {
                                 _this._loadingMaterialLOD = materialLOD;
-                                _this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
+                                if (!_this._loadMaterialSignals[materialLOD._index]) {
+                                    _this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
+                                }
                             }
                             var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh).then(function () {
                                 if (indexLOD !== materialLODs.length - 1) {
                                     var materialIndex = materialLODs[indexLOD + 1]._index;
-                                    _this._loadMaterialSignals[materialIndex].resolve();
-                                    delete _this._loadMaterialSignals[materialIndex];
+                                    if (_this._loadMaterialSignals[materialIndex]) {
+                                        _this._loadMaterialSignals[materialIndex].resolve();
+                                        delete _this._loadMaterialSignals[materialIndex];
+                                    }
                                 }
                             });
                             if (indexLOD === 0) {

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 17 - 8
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3250,8 +3250,9 @@ var BABYLON;
                     node._babylonMesh.scaling = BABYLON.Vector3.One();
                 };
                 if (skin._loaded) {
-                    assignSkeleton();
-                    return skin._loaded;
+                    return skin._loaded.then(function () {
+                        assignSkeleton();
+                    });
                 }
                 // TODO: split into two parts so that bones are created before inverseBindMatricesData is loaded (for compiling materials).
                 return (skin._loaded = this._loadSkinInverseBindMatricesDataAsync(context, skin).then(function (inverseBindMatricesData) {
@@ -4138,7 +4139,9 @@ var BABYLON;
                             var nodeLOD = nodeLODs[indexLOD];
                             if (indexLOD !== 0) {
                                 _this._loadingNodeLOD = nodeLOD;
-                                _this._loadNodeSignals[nodeLOD._index] = new BABYLON.Deferred();
+                                if (!_this._loadNodeSignals[nodeLOD._index]) {
+                                    _this._loadNodeSignals[nodeLOD._index] = new BABYLON.Deferred();
+                                }
                             }
                             var promise = _this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(function () {
                                 if (indexLOD !== 0) {
@@ -4147,8 +4150,10 @@ var BABYLON;
                                 }
                                 if (indexLOD !== nodeLODs.length - 1) {
                                     var nodeIndex = nodeLODs[indexLOD + 1]._index;
-                                    _this._loadNodeSignals[nodeIndex].resolve();
-                                    delete _this._loadNodeSignals[nodeIndex];
+                                    if (_this._loadNodeSignals[nodeIndex]) {
+                                        _this._loadNodeSignals[nodeIndex].resolve();
+                                        delete _this._loadNodeSignals[nodeIndex];
+                                    }
                                 }
                             });
                             if (indexLOD === 0) {
@@ -4178,13 +4183,17 @@ var BABYLON;
                             var materialLOD = materialLODs[indexLOD];
                             if (indexLOD !== 0) {
                                 _this._loadingMaterialLOD = materialLOD;
-                                _this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
+                                if (!_this._loadMaterialSignals[materialLOD._index]) {
+                                    _this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
+                                }
                             }
                             var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh).then(function () {
                                 if (indexLOD !== materialLODs.length - 1) {
                                     var materialIndex = materialLODs[indexLOD + 1]._index;
-                                    _this._loadMaterialSignals[materialIndex].resolve();
-                                    delete _this._loadMaterialSignals[materialIndex];
+                                    if (_this._loadMaterialSignals[materialIndex]) {
+                                        _this._loadMaterialSignals[materialIndex].resolve();
+                                        delete _this._loadMaterialSignals[materialIndex];
+                                    }
                                 }
                             });
                             if (indexLOD === 0) {

File diff suppressed because it is too large
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 31 - 28
dist/preview release/loaders/babylonjs.loaders.js

@@ -1,6 +1,3 @@
-var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-var babylonDependency = (globalObject && globalObject.BABYLON) || BABYLON || (typeof require !== 'undefined' && require("babylonjs"));
-var BABYLON = babylonDependency;
 var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -18,6 +15,19 @@ var __extends = (this && this.__extends) || (function () {
             };
         })();
         
+
+(function universalModuleDefinition(root, factory) {
+    if(typeof exports === 'object' && typeof module === 'object')
+        module.exports = factory(require("babylonjs"));
+    else if(typeof define === 'function' && define.amd)
+        define("babylonjs-loaders", ["babylonjs"], factory);
+    else if(typeof exports === 'object')
+        exports["babylonjs-loaders"] = factory(require("babylonjs"));
+    else {
+        root["BABYLON"] = factory(root["BABYLON"]);
+    }
+})(this, function(BABYLON) {
+    
 var BABYLON;
 (function (BABYLON) {
     var STLFileLoader = /** @class */ (function () {
@@ -4218,8 +4228,9 @@ var BABYLON;
                     node._babylonMesh.scaling = BABYLON.Vector3.One();
                 };
                 if (skin._loaded) {
-                    assignSkeleton();
-                    return skin._loaded;
+                    return skin._loaded.then(function () {
+                        assignSkeleton();
+                    });
                 }
                 // TODO: split into two parts so that bones are created before inverseBindMatricesData is loaded (for compiling materials).
                 return (skin._loaded = this._loadSkinInverseBindMatricesDataAsync(context, skin).then(function (inverseBindMatricesData) {
@@ -5097,7 +5108,9 @@ var BABYLON;
                             var nodeLOD = nodeLODs[indexLOD];
                             if (indexLOD !== 0) {
                                 _this._loadingNodeLOD = nodeLOD;
-                                _this._loadNodeSignals[nodeLOD._index] = new BABYLON.Deferred();
+                                if (!_this._loadNodeSignals[nodeLOD._index]) {
+                                    _this._loadNodeSignals[nodeLOD._index] = new BABYLON.Deferred();
+                                }
                             }
                             var promise = _this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(function () {
                                 if (indexLOD !== 0) {
@@ -5106,8 +5119,10 @@ var BABYLON;
                                 }
                                 if (indexLOD !== nodeLODs.length - 1) {
                                     var nodeIndex = nodeLODs[indexLOD + 1]._index;
-                                    _this._loadNodeSignals[nodeIndex].resolve();
-                                    delete _this._loadNodeSignals[nodeIndex];
+                                    if (_this._loadNodeSignals[nodeIndex]) {
+                                        _this._loadNodeSignals[nodeIndex].resolve();
+                                        delete _this._loadNodeSignals[nodeIndex];
+                                    }
                                 }
                             });
                             if (indexLOD === 0) {
@@ -5137,13 +5152,17 @@ var BABYLON;
                             var materialLOD = materialLODs[indexLOD];
                             if (indexLOD !== 0) {
                                 _this._loadingMaterialLOD = materialLOD;
-                                _this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
+                                if (!_this._loadMaterialSignals[materialLOD._index]) {
+                                    _this._loadMaterialSignals[materialLOD._index] = new BABYLON.Deferred();
+                                }
                             }
                             var promise = _this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh).then(function () {
                                 if (indexLOD !== materialLODs.length - 1) {
                                     var materialIndex = materialLODs[indexLOD + 1]._index;
-                                    _this._loadMaterialSignals[materialIndex].resolve();
-                                    delete _this._loadMaterialSignals[materialIndex];
+                                    if (_this._loadMaterialSignals[materialIndex]) {
+                                        _this._loadMaterialSignals[materialIndex].resolve();
+                                        delete _this._loadMaterialSignals[materialIndex];
+                                    }
                                 }
                             });
                             if (indexLOD === 0) {
@@ -5457,22 +5476,6 @@ var BABYLON;
 
 //# sourceMappingURL=KHR_lights.js.map
 
-
-(function universalModuleDefinition(root, factory) {
-                var f = factory();
-                if (root && root["BABYLON"]) {
-                    return;
-                }
-                
-    if(typeof exports === 'object' && typeof module === 'object')
-        module.exports = f;
-    else if(typeof define === 'function' && define.amd)
-        define(["BJSLoaders"], factory);
-    else if(typeof exports === 'object')
-        exports["BJSLoaders"] = f;
-    else {
-        root["BABYLON"] = f;
-    }
-})(this, function() {
+    
     return BABYLON;
 });

File diff suppressed because it is too large
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -1,4 +1,5 @@
 /// <reference types="babylonjs"/>
+/// <reference types="babylonjs-gltf2interface"/>
 
 
 declare module 'babylonjs-loaders' { 

+ 4 - 1
dist/preview release/loaders/package.json

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

+ 1 - 0
dist/preview release/materialsLibrary/babylon.customMaterial.d.ts

@@ -73,6 +73,7 @@ declare module BABYLON {
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
         EXPOSURE: boolean;
+        GRAIN: boolean;
         constructor();
         setReflectionMode(modeToEnable: string): void;
     }

+ 1 - 0
dist/preview release/materialsLibrary/babylon.customMaterial.js

@@ -94,6 +94,7 @@ var BABYLON;
             _this.SAMPLER3DBGRMAP = false;
             _this.IMAGEPROCESSINGPOSTPROCESS = false;
             _this.EXPOSURE = false;
+            _this.GRAIN = false;
             _this.rebuild();
             return _this;
         }

File diff suppressed because it is too large
+ 2 - 2
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


File diff suppressed because it is too large
+ 15 - 20
dist/preview release/materialsLibrary/babylonjs.materials.js


File diff suppressed because it is too large
+ 7 - 7
dist/preview release/materialsLibrary/babylonjs.materials.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts

@@ -579,6 +579,7 @@ declare module BABYLON {
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
         EXPOSURE: boolean;
+        GRAIN: boolean;
         constructor();
         setReflectionMode(modeToEnable: string): void;
     }

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

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

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


File diff suppressed because it is too large
+ 14 - 20
dist/preview release/postProcessesLibrary/babylonjs.postProcess.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


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

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

File diff suppressed because it is too large
+ 14 - 20
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js


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

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

+ 42 - 0
dist/preview release/serializers/babylon.glTF2Serializer.d.ts

@@ -295,6 +295,7 @@ declare module BABYLON.GLTF2 {
          * Allows the maximum specular power to be defined for material calculations.
          */
         private static maxSpecularPower;
+        private static epsilon;
         /**
          * Gets the materials from a Babylon scene and converts them to glTF materials.
          * @param scene
@@ -312,6 +313,18 @@ declare module BABYLON.GLTF2 {
             };
         }, hasTextureCoords: boolean): void;
         /**
+         * Makes a copy of the glTF material without the texture parameters.
+         * @param originalMaterial - original glTF material.
+         * @returns glTF material without texture parameters
+         */
+        static StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
+        /**
+         * Specifies if the material has any texture parameters present.
+         * @param material - glTF Material.
+         * @returns boolean specifying if texture parameters are present
+         */
+        static HasTexturesPresent(material: IMaterial): boolean;
+        /**
          * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
          * @param babylonStandardMaterial
          * @returns - glTF Metallic Roughness Material representation
@@ -364,6 +377,35 @@ declare module BABYLON.GLTF2 {
             };
         }, hasTextureCoords: boolean): void;
         /**
+         * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
+         * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+         * @param color - Color source to calculate brightness from.
+         * @returns number representing the perceived brightness, or zero if color is undefined.
+         */
+        static GetPerceivedBrightness(color: Color3): number;
+        /**
+         * Returns the maximum color component value.
+         * @param color
+         * @returns maximum color component value, or zero if color is null or undefined.
+         */
+        static GetMaxComponent(color: Color3): number;
+        /**
+         * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
+         * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
+         * @param mimeType - mime type to use for the textures.
+         * @param images - array of glTF image interfaces.
+         * @param textures - array of glTF texture interfaces.
+         * @param materials - array of glTF material interfaces.
+         * @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.
+         */
+        static ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+            [fileName: string]: {
+                data: Uint8Array;
+                mimeType: ImageMimeType;
+            };
+        }, hasTextureCoords: boolean): void;
+        /**
          * Extracts a texture from a Babylon texture into file data and glTF data.
          * @param babylonTexture - Babylon texture to extract.
          * @param mimeType - Mime Type of the babylonTexture.

+ 262 - 31
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -80,7 +80,7 @@ var BABYLON;
                 this.materials = new Array();
                 this.textures = new Array();
                 this.imageData = {};
-                this.convertToRightHandedSystem = !this.babylonScene.useRightHandedSystem;
+                this.convertToRightHandedSystem = this.babylonScene.useRightHandedSystem ? false : true;
                 if (options) {
                     this.options = options;
                 }
@@ -411,10 +411,10 @@ var BABYLON;
              * @param babylonMesh - Babylon mesh used as the source for the transformation data.
              */
             _Exporter.prototype.setNodeTransformation = function (node, babylonMesh) {
-                if (!(babylonMesh.position.x === 0 && babylonMesh.position.y === 0 && babylonMesh.position.z === 0)) {
+                if (!babylonMesh.position.equalsToFloats(0, 0, 0)) {
                     node.translation = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(babylonMesh.position).asArray() : babylonMesh.position.asArray();
                 }
-                if (!(babylonMesh.scaling.x === 1 && babylonMesh.scaling.y === 1 && babylonMesh.scaling.z === 1)) {
+                if (!babylonMesh.scaling.equalsToFloats(1, 1, 1)) {
                     node.scale = babylonMesh.scaling.asArray();
                 }
                 var rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(babylonMesh.rotation.y, babylonMesh.rotation.x, babylonMesh.rotation.z);
@@ -527,6 +527,7 @@ var BABYLON;
                         }
                     }
                     if (babylonMesh.subMeshes) {
+                        var uvCoordsPresent = false;
                         // go through all mesh primitives (submeshes)
                         for (var _a = 0, _b = babylonMesh.subMeshes; _a < _b.length; _a++) {
                             var submesh = _b[_a];
@@ -573,10 +574,12 @@ var BABYLON;
                                                         }
                                                         case BABYLON.VertexBuffer.UVKind: {
                                                             meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
+                                                            uvCoordsPresent = true;
                                                             break;
                                                         }
                                                         case BABYLON.VertexBuffer.UV2Kind: {
                                                             meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                                                            uvCoordsPresent = true;
                                                             break;
                                                         }
                                                         default: {
@@ -596,21 +599,31 @@ var BABYLON;
                                 }
                             }
                             if (bufferMesh.material) {
-                                if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                                    var materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
-                                    meshPrimitive.material = materialIndex;
+                                var materialIndex = null;
+                                if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial || bufferMesh.material instanceof BABYLON.PBRMaterial) {
+                                    materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
                                 }
                                 else if (bufferMesh.material instanceof BABYLON.MultiMaterial) {
                                     var babylonMultiMaterial = bufferMesh.material;
                                     var material = babylonMultiMaterial.subMaterials[submesh.materialIndex];
                                     if (material) {
-                                        var materialIndex = babylonMesh.getScene().materials.indexOf(material);
-                                        meshPrimitive.material = materialIndex;
+                                        materialIndex = babylonMesh.getScene().materials.indexOf(material);
                                     }
                                 }
                                 else {
                                     BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
                                 }
+                                if (materialIndex != null) {
+                                    if (uvCoordsPresent || !GLTF2._GLTFMaterial.HasTexturesPresent(this.materials[materialIndex])) {
+                                        meshPrimitive.material = materialIndex;
+                                    }
+                                    else {
+                                        // If no texture coordinate information is present, make a copy of the material without the textures to be glTF compliant.
+                                        var newMat = GLTF2._GLTFMaterial.StripTexturesFromMaterial(this.materials[materialIndex]);
+                                        this.materials.push(newMat);
+                                        meshPrimitive.material = this.materials.length - 1;
+                                    }
+                                }
                             }
                             mesh.primitives.push(meshPrimitive);
                         }
@@ -636,30 +649,30 @@ var BABYLON;
                     this.binaryBuffer = new ArrayBuffer(this.totalByteLength);
                     var dataBuffer = new DataView(this.binaryBuffer);
                     for (var i = 0; i < babylonMeshes.length; ++i) {
-                        if (this.options &&
-                            this.options.shouldExportMesh != undefined &&
-                            !this.options.shouldExportMesh(babylonMeshes[i])) {
-                            continue;
-                        }
-                        else {
-                            var babylonMesh = babylonMeshes[i];
-                            // Build Hierarchy with the node map.
-                            var glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
-                            var glTFNode = this.nodes[glTFNodeIndex];
-                            if (!babylonMesh.parent) {
+                        var babylonMesh = babylonMeshes[i];
+                        // Build Hierarchy with the node map.
+                        var glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
+                        var glTFNode = this.nodes[glTFNodeIndex];
+                        if (!babylonMesh.parent) {
+                            if (this.options &&
+                                this.options.shouldExportMesh != undefined &&
+                                !this.options.shouldExportMesh(babylonMesh)) {
+                                BABYLON.Tools.Log("Omitting " + babylonMesh.name + " from scene.");
+                            }
+                            else {
                                 scene.nodes.push(glTFNodeIndex);
                             }
-                            var directDescendents = babylonMesh.getDescendants(true);
-                            if (!glTFNode.children && directDescendents && directDescendents.length) {
-                                glTFNode.children = [];
-                                for (var _i = 0, directDescendents_1 = directDescendents; _i < directDescendents_1.length; _i++) {
-                                    var descendent = directDescendents_1[_i];
-                                    glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
-                                }
+                        }
+                        var directDescendents = babylonMesh.getDescendants(true);
+                        if (!glTFNode.children && directDescendents && directDescendents.length) {
+                            glTFNode.children = [];
+                            for (var _i = 0, directDescendents_1 = directDescendents; _i < directDescendents_1.length; _i++) {
+                                var descendent = directDescendents_1[_i];
+                                glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
                             }
-                            var mesh = { primitives: new Array() };
-                            byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
                         }
+                        var mesh = { primitives: new Array() };
+                        byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
                     }
                     this.scenes.push(scene);
                 }
@@ -804,7 +817,53 @@ var BABYLON;
                     else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
                         _GLTFMaterial.ConvertPBRMetallicRoughnessMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
+                    else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
+                        _GLTFMaterial.ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                    }
+                    else {
+                        BABYLON.Tools.Error("Unsupported material type: " + babylonMaterial.name);
+                    }
+                }
+            };
+            /**
+             * Makes a copy of the glTF material without the texture parameters.
+             * @param originalMaterial - original glTF material.
+             * @returns glTF material without texture parameters
+             */
+            _GLTFMaterial.StripTexturesFromMaterial = function (originalMaterial) {
+                var newMaterial = {};
+                if (originalMaterial) {
+                    newMaterial.name = originalMaterial.name;
+                    newMaterial.doubleSided = originalMaterial.doubleSided;
+                    newMaterial.alphaMode = originalMaterial.alphaMode;
+                    newMaterial.alphaCutoff = originalMaterial.alphaCutoff;
+                    newMaterial.emissiveFactor = originalMaterial.emissiveFactor;
+                    var originalPBRMetallicRoughness = originalMaterial.pbrMetallicRoughness;
+                    if (originalPBRMetallicRoughness) {
+                        newMaterial.pbrMetallicRoughness = {};
+                        newMaterial.pbrMetallicRoughness.baseColorFactor = originalPBRMetallicRoughness.baseColorFactor;
+                        newMaterial.pbrMetallicRoughness.metallicFactor = originalPBRMetallicRoughness.metallicFactor;
+                        newMaterial.pbrMetallicRoughness.roughnessFactor = originalPBRMetallicRoughness.roughnessFactor;
+                    }
                 }
+                return newMaterial;
+            };
+            /**
+             * Specifies if the material has any texture parameters present.
+             * @param material - glTF Material.
+             * @returns boolean specifying if texture parameters are present
+             */
+            _GLTFMaterial.HasTexturesPresent = function (material) {
+                if (material.emissiveTexture || material.normalTexture || material.occlusionTexture) {
+                    return true;
+                }
+                var pbrMat = material.pbrMetallicRoughness;
+                if (pbrMat) {
+                    if (pbrMat.baseColorTexture || pbrMat.metallicRoughnessTexture) {
+                        return true;
+                    }
+                }
+                return false;
             };
             /**
              * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
@@ -914,6 +973,27 @@ var BABYLON;
                         }
                     }
                 }
+                else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
+                    var babylonPBRMaterial = babylonMaterial;
+                    switch (babylonPBRMaterial.transparencyMode) {
+                        case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
+                            return "OPAQUE" /* OPAQUE */;
+                        }
+                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
+                            return "BLEND" /* BLEND */;
+                        }
+                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
+                            return "MASK" /* MASK */;
+                        }
+                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
+                            BABYLON.Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
+                            return "BLEND" /* BLEND */;
+                        }
+                        default: {
+                            throw new Error("Unsupported alpha mode " + babylonPBRMaterial.transparencyMode);
+                        }
+                    }
+                }
                 else {
                     throw new Error("Unsupported Babylon material type");
                 }
@@ -959,9 +1039,13 @@ var BABYLON;
                         glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
                     }
                     if (babylonStandardMaterial.ambientTexture) {
-                        var glTFOcclusionTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
-                        if (glTFOcclusionTexture) {
-                            glTFMaterial.occlusionTexture = glTFOcclusionTexture;
+                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            var occlusionTexture = {
+                                index: glTFTexture.index
+                            };
+                            glTFMaterial.occlusionTexture = occlusionTexture;
+                            occlusionTexture.strength = 1.0;
                         }
                     }
                 }
@@ -973,6 +1057,9 @@ var BABYLON;
                         BABYLON.Tools.Warn(babylonStandardMaterial.name + ": glTF 2.0 does not support alpha mode: " + babylonStandardMaterial.alphaMode.toString());
                     }
                 }
+                if (babylonStandardMaterial.emissiveColor) {
+                    glTFMaterial.emissiveFactor = babylonStandardMaterial.emissiveColor.asArray();
+                }
                 glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
                 materials.push(glTFMaterial);
             };
@@ -1053,6 +1140,149 @@ var BABYLON;
                 materials.push(glTFMaterial);
             };
             /**
+             * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
+             * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+             * @param color - Color source to calculate brightness from.
+             * @returns number representing the perceived brightness, or zero if color is undefined.
+             */
+            _GLTFMaterial.GetPerceivedBrightness = function (color) {
+                if (color) {
+                    return Math.sqrt(0.299 * color.r * color.r + 0.587 * color.g * color.g + 0.114 * color.b * color.b);
+                }
+                return 0;
+            };
+            /**
+             * Returns the maximum color component value.
+             * @param color
+             * @returns maximum color component value, or zero if color is null or undefined.
+             */
+            _GLTFMaterial.GetMaxComponent = function (color) {
+                if (color) {
+                    return Math.max(color.r, Math.max(color.g, color.b));
+                }
+                return 0;
+            };
+            /**
+             * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
+             * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
+             * @param mimeType - mime type to use for the textures.
+             * @param images - array of glTF image interfaces.
+             * @param textures - array of glTF texture interfaces.
+             * @param materials - array of glTF material interfaces.
+             * @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.
+             */
+            _GLTFMaterial.ConvertPBRMaterial = function (babylonPBRMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+                var glTFPbrMetallicRoughness = {};
+                var glTFMaterial = {
+                    name: babylonPBRMaterial.name
+                };
+                var useMetallicRoughness = babylonPBRMaterial.isMetallicWorkflow();
+                if (babylonPBRMaterial) {
+                    if (useMetallicRoughness) {
+                        glTFPbrMetallicRoughness.baseColorFactor = [
+                            babylonPBRMaterial.albedoColor.r,
+                            babylonPBRMaterial.albedoColor.g,
+                            babylonPBRMaterial.albedoColor.b,
+                            babylonPBRMaterial.alpha
+                        ];
+                        if (babylonPBRMaterial.metallic != null) {
+                            if (babylonPBRMaterial.metallic !== 1) {
+                                glTFPbrMetallicRoughness.metallicFactor = babylonPBRMaterial.metallic;
+                            }
+                        }
+                        if (babylonPBRMaterial.roughness != null) {
+                            if (babylonPBRMaterial.roughness !== 1) {
+                                glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
+                            }
+                        }
+                    }
+                    else {
+                        var diffuseColor = babylonPBRMaterial.albedoColor || BABYLON.Color3.Black();
+                        var specularColor = babylonPBRMaterial.reflectionColor || BABYLON.Color3.Black();
+                        var diffusePerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(diffuseColor);
+                        var specularPerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(specularColor);
+                        var oneMinusSpecularStrength = 1 - _GLTFMaterial.GetMaxComponent(babylonPBRMaterial.reflectionColor);
+                        var metallic = _GLTFMaterial.SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
+                        var glossiness = babylonPBRMaterial.microSurface || 0;
+                        var baseColorFromDiffuse = diffuseColor.scale(oneMinusSpecularStrength / (1.0 - this.dielectricSpecular.r) / Math.max(1 - metallic, this.epsilon));
+                        var baseColorFromSpecular = specularColor.subtract(this.dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this.epsilon));
+                        var baseColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
+                        baseColor = baseColor.clampToRef(0, 1, baseColor);
+                        glTFPbrMetallicRoughness.baseColorFactor = [
+                            baseColor.r,
+                            baseColor.g,
+                            baseColor.b,
+                            babylonPBRMaterial.alpha
+                        ];
+                        if (metallic !== 1) {
+                            glTFPbrMetallicRoughness.metallicFactor = metallic;
+                        }
+                        if (glossiness) {
+                            glTFPbrMetallicRoughness.roughnessFactor = 1 - glossiness;
+                        }
+                    }
+                    if (babylonPBRMaterial.backFaceCulling) {
+                        if (!babylonPBRMaterial.twoSidedLighting) {
+                            BABYLON.Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
+                        }
+                        glTFMaterial.doubleSided = true;
+                    }
+                    if (hasTextureCoords) {
+                        if (babylonPBRMaterial.albedoTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.albedoTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.bumpTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.ambientTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture) {
+                                var occlusionTexture = {
+                                    index: glTFTexture.index
+                                };
+                                glTFMaterial.occlusionTexture = occlusionTexture;
+                                if (babylonPBRMaterial.ambientTextureStrength) {
+                                    occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
+                                }
+                            }
+                        }
+                        if (babylonPBRMaterial.emissiveTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture != null) {
+                                glTFMaterial.emissiveTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.metallicTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.metallicTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture != null) {
+                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
+                            }
+                        }
+                    }
+                    if (!babylonPBRMaterial.emissiveColor.equalsFloats(0.0, 0.0, 0.0)) {
+                        glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                    }
+                    if (babylonPBRMaterial.transparencyMode != null) {
+                        var alphaMode = _GLTFMaterial.GetAlphaMode(babylonPBRMaterial);
+                        if (alphaMode !== "OPAQUE" /* OPAQUE */) {
+                            glTFMaterial.alphaMode = alphaMode;
+                            if (alphaMode === "BLEND" /* BLEND */) {
+                                glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
+                            }
+                        }
+                    }
+                }
+                glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
+                materials.push(glTFMaterial);
+            };
+            /**
              * Extracts a texture from a Babylon texture into file data and glTF data.
              * @param babylonTexture - Babylon texture to extract.
              * @param mimeType - Mime Type of the babylonTexture.
@@ -1140,6 +1370,7 @@ var BABYLON;
              * Allows the maximum specular power to be defined for material calculations.
              */
             _GLTFMaterial.maxSpecularPower = 1024;
+            _GLTFMaterial.epsilon = 1e-6;
             return _GLTFMaterial;
         }());
         GLTF2._GLTFMaterial = _GLTFMaterial;

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


+ 276 - 51
dist/preview release/serializers/babylonjs.serializers.js

@@ -1,6 +1,3 @@
-var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-var babylonDependency = (globalObject && globalObject.BABYLON) || BABYLON || (typeof require !== 'undefined' && require("babylonjs"));
-var BABYLON = babylonDependency;
 var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -18,6 +15,19 @@ var __extends = (this && this.__extends) || (function () {
             };
         })();
         
+
+(function universalModuleDefinition(root, factory) {
+    if(typeof exports === 'object' && typeof module === 'object')
+        module.exports = factory(require("babylonjs"));
+    else if(typeof define === 'function' && define.amd)
+        define("babylonjs-serializers", ["babylonjs"], factory);
+    else if(typeof exports === 'object')
+        exports["babylonjs-serializers"] = factory(require("babylonjs"));
+    else {
+        root["BABYLON"] = factory(root["BABYLON"]);
+    }
+})(this, function(BABYLON) {
+    
 var BABYLON;
 (function (BABYLON) {
     var OBJExport = /** @class */ (function () {
@@ -224,7 +234,7 @@ var BABYLON;
                 this.materials = new Array();
                 this.textures = new Array();
                 this.imageData = {};
-                this.convertToRightHandedSystem = !this.babylonScene.useRightHandedSystem;
+                this.convertToRightHandedSystem = this.babylonScene.useRightHandedSystem ? false : true;
                 if (options) {
                     this.options = options;
                 }
@@ -555,10 +565,10 @@ var BABYLON;
              * @param babylonMesh - Babylon mesh used as the source for the transformation data.
              */
             _Exporter.prototype.setNodeTransformation = function (node, babylonMesh) {
-                if (!(babylonMesh.position.x === 0 && babylonMesh.position.y === 0 && babylonMesh.position.z === 0)) {
+                if (!babylonMesh.position.equalsToFloats(0, 0, 0)) {
                     node.translation = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(babylonMesh.position).asArray() : babylonMesh.position.asArray();
                 }
-                if (!(babylonMesh.scaling.x === 1 && babylonMesh.scaling.y === 1 && babylonMesh.scaling.z === 1)) {
+                if (!babylonMesh.scaling.equalsToFloats(1, 1, 1)) {
                     node.scale = babylonMesh.scaling.asArray();
                 }
                 var rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(babylonMesh.rotation.y, babylonMesh.rotation.x, babylonMesh.rotation.z);
@@ -671,6 +681,7 @@ var BABYLON;
                         }
                     }
                     if (babylonMesh.subMeshes) {
+                        var uvCoordsPresent = false;
                         // go through all mesh primitives (submeshes)
                         for (var _a = 0, _b = babylonMesh.subMeshes; _a < _b.length; _a++) {
                             var submesh = _b[_a];
@@ -717,10 +728,12 @@ var BABYLON;
                                                         }
                                                         case BABYLON.VertexBuffer.UVKind: {
                                                             meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
+                                                            uvCoordsPresent = true;
                                                             break;
                                                         }
                                                         case BABYLON.VertexBuffer.UV2Kind: {
                                                             meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                                                            uvCoordsPresent = true;
                                                             break;
                                                         }
                                                         default: {
@@ -740,21 +753,31 @@ var BABYLON;
                                 }
                             }
                             if (bufferMesh.material) {
-                                if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial) {
-                                    var materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
-                                    meshPrimitive.material = materialIndex;
+                                var materialIndex = null;
+                                if (bufferMesh.material instanceof BABYLON.StandardMaterial || bufferMesh.material instanceof BABYLON.PBRMetallicRoughnessMaterial || bufferMesh.material instanceof BABYLON.PBRMaterial) {
+                                    materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
                                 }
                                 else if (bufferMesh.material instanceof BABYLON.MultiMaterial) {
                                     var babylonMultiMaterial = bufferMesh.material;
                                     var material = babylonMultiMaterial.subMaterials[submesh.materialIndex];
                                     if (material) {
-                                        var materialIndex = babylonMesh.getScene().materials.indexOf(material);
-                                        meshPrimitive.material = materialIndex;
+                                        materialIndex = babylonMesh.getScene().materials.indexOf(material);
                                     }
                                 }
                                 else {
                                     BABYLON.Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
                                 }
+                                if (materialIndex != null) {
+                                    if (uvCoordsPresent || !GLTF2._GLTFMaterial.HasTexturesPresent(this.materials[materialIndex])) {
+                                        meshPrimitive.material = materialIndex;
+                                    }
+                                    else {
+                                        // If no texture coordinate information is present, make a copy of the material without the textures to be glTF compliant.
+                                        var newMat = GLTF2._GLTFMaterial.StripTexturesFromMaterial(this.materials[materialIndex]);
+                                        this.materials.push(newMat);
+                                        meshPrimitive.material = this.materials.length - 1;
+                                    }
+                                }
                             }
                             mesh.primitives.push(meshPrimitive);
                         }
@@ -780,30 +803,30 @@ var BABYLON;
                     this.binaryBuffer = new ArrayBuffer(this.totalByteLength);
                     var dataBuffer = new DataView(this.binaryBuffer);
                     for (var i = 0; i < babylonMeshes.length; ++i) {
-                        if (this.options &&
-                            this.options.shouldExportMesh != undefined &&
-                            !this.options.shouldExportMesh(babylonMeshes[i])) {
-                            continue;
-                        }
-                        else {
-                            var babylonMesh = babylonMeshes[i];
-                            // Build Hierarchy with the node map.
-                            var glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
-                            var glTFNode = this.nodes[glTFNodeIndex];
-                            if (!babylonMesh.parent) {
+                        var babylonMesh = babylonMeshes[i];
+                        // Build Hierarchy with the node map.
+                        var glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
+                        var glTFNode = this.nodes[glTFNodeIndex];
+                        if (!babylonMesh.parent) {
+                            if (this.options &&
+                                this.options.shouldExportMesh != undefined &&
+                                !this.options.shouldExportMesh(babylonMesh)) {
+                                BABYLON.Tools.Log("Omitting " + babylonMesh.name + " from scene.");
+                            }
+                            else {
                                 scene.nodes.push(glTFNodeIndex);
                             }
-                            var directDescendents = babylonMesh.getDescendants(true);
-                            if (!glTFNode.children && directDescendents && directDescendents.length) {
-                                glTFNode.children = [];
-                                for (var _i = 0, directDescendents_1 = directDescendents; _i < directDescendents_1.length; _i++) {
-                                    var descendent = directDescendents_1[_i];
-                                    glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
-                                }
+                        }
+                        var directDescendents = babylonMesh.getDescendants(true);
+                        if (!glTFNode.children && directDescendents && directDescendents.length) {
+                            glTFNode.children = [];
+                            for (var _i = 0, directDescendents_1 = directDescendents; _i < directDescendents_1.length; _i++) {
+                                var descendent = directDescendents_1[_i];
+                                glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
                             }
-                            var mesh = { primitives: new Array() };
-                            byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
                         }
+                        var mesh = { primitives: new Array() };
+                        byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
                     }
                     this.scenes.push(scene);
                 }
@@ -948,7 +971,53 @@ var BABYLON;
                     else if (babylonMaterial instanceof BABYLON.PBRMetallicRoughnessMaterial) {
                         _GLTFMaterial.ConvertPBRMetallicRoughnessMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
                     }
+                    else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
+                        _GLTFMaterial.ConvertPBRMaterial(babylonMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords);
+                    }
+                    else {
+                        BABYLON.Tools.Error("Unsupported material type: " + babylonMaterial.name);
+                    }
+                }
+            };
+            /**
+             * Makes a copy of the glTF material without the texture parameters.
+             * @param originalMaterial - original glTF material.
+             * @returns glTF material without texture parameters
+             */
+            _GLTFMaterial.StripTexturesFromMaterial = function (originalMaterial) {
+                var newMaterial = {};
+                if (originalMaterial) {
+                    newMaterial.name = originalMaterial.name;
+                    newMaterial.doubleSided = originalMaterial.doubleSided;
+                    newMaterial.alphaMode = originalMaterial.alphaMode;
+                    newMaterial.alphaCutoff = originalMaterial.alphaCutoff;
+                    newMaterial.emissiveFactor = originalMaterial.emissiveFactor;
+                    var originalPBRMetallicRoughness = originalMaterial.pbrMetallicRoughness;
+                    if (originalPBRMetallicRoughness) {
+                        newMaterial.pbrMetallicRoughness = {};
+                        newMaterial.pbrMetallicRoughness.baseColorFactor = originalPBRMetallicRoughness.baseColorFactor;
+                        newMaterial.pbrMetallicRoughness.metallicFactor = originalPBRMetallicRoughness.metallicFactor;
+                        newMaterial.pbrMetallicRoughness.roughnessFactor = originalPBRMetallicRoughness.roughnessFactor;
+                    }
+                }
+                return newMaterial;
+            };
+            /**
+             * Specifies if the material has any texture parameters present.
+             * @param material - glTF Material.
+             * @returns boolean specifying if texture parameters are present
+             */
+            _GLTFMaterial.HasTexturesPresent = function (material) {
+                if (material.emissiveTexture || material.normalTexture || material.occlusionTexture) {
+                    return true;
+                }
+                var pbrMat = material.pbrMetallicRoughness;
+                if (pbrMat) {
+                    if (pbrMat.baseColorTexture || pbrMat.metallicRoughnessTexture) {
+                        return true;
+                    }
                 }
+                return false;
             };
             /**
              * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
@@ -1058,6 +1127,27 @@ var BABYLON;
                         }
                     }
                 }
+                else if (babylonMaterial instanceof BABYLON.PBRMaterial) {
+                    var babylonPBRMaterial = babylonMaterial;
+                    switch (babylonPBRMaterial.transparencyMode) {
+                        case BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE: {
+                            return "OPAQUE" /* OPAQUE */;
+                        }
+                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND: {
+                            return "BLEND" /* BLEND */;
+                        }
+                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATEST: {
+                            return "MASK" /* MASK */;
+                        }
+                        case BABYLON.PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
+                            BABYLON.Tools.Warn(babylonMaterial.name + ": GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
+                            return "BLEND" /* BLEND */;
+                        }
+                        default: {
+                            throw new Error("Unsupported alpha mode " + babylonPBRMaterial.transparencyMode);
+                        }
+                    }
+                }
                 else {
                     throw new Error("Unsupported Babylon material type");
                 }
@@ -1103,9 +1193,13 @@ var BABYLON;
                         glTFMaterial.emissiveFactor = [1.0, 1.0, 1.0];
                     }
                     if (babylonStandardMaterial.ambientTexture) {
-                        var glTFOcclusionTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
-                        if (glTFOcclusionTexture) {
-                            glTFMaterial.occlusionTexture = glTFOcclusionTexture;
+                        var glTFTexture = _GLTFMaterial.ExportTexture(babylonStandardMaterial.ambientTexture, mimeType, images, textures, imageData);
+                        if (glTFTexture) {
+                            var occlusionTexture = {
+                                index: glTFTexture.index
+                            };
+                            glTFMaterial.occlusionTexture = occlusionTexture;
+                            occlusionTexture.strength = 1.0;
                         }
                     }
                 }
@@ -1117,6 +1211,9 @@ var BABYLON;
                         BABYLON.Tools.Warn(babylonStandardMaterial.name + ": glTF 2.0 does not support alpha mode: " + babylonStandardMaterial.alphaMode.toString());
                     }
                 }
+                if (babylonStandardMaterial.emissiveColor) {
+                    glTFMaterial.emissiveFactor = babylonStandardMaterial.emissiveColor.asArray();
+                }
                 glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
                 materials.push(glTFMaterial);
             };
@@ -1197,6 +1294,149 @@ var BABYLON;
                 materials.push(glTFMaterial);
             };
             /**
+             * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
+             * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+             * @param color - Color source to calculate brightness from.
+             * @returns number representing the perceived brightness, or zero if color is undefined.
+             */
+            _GLTFMaterial.GetPerceivedBrightness = function (color) {
+                if (color) {
+                    return Math.sqrt(0.299 * color.r * color.r + 0.587 * color.g * color.g + 0.114 * color.b * color.b);
+                }
+                return 0;
+            };
+            /**
+             * Returns the maximum color component value.
+             * @param color
+             * @returns maximum color component value, or zero if color is null or undefined.
+             */
+            _GLTFMaterial.GetMaxComponent = function (color) {
+                if (color) {
+                    return Math.max(color.r, Math.max(color.g, color.b));
+                }
+                return 0;
+            };
+            /**
+             * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
+             * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
+             * @param mimeType - mime type to use for the textures.
+             * @param images - array of glTF image interfaces.
+             * @param textures - array of glTF texture interfaces.
+             * @param materials - array of glTF material interfaces.
+             * @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.
+             */
+            _GLTFMaterial.ConvertPBRMaterial = function (babylonPBRMaterial, mimeType, images, textures, materials, imageData, hasTextureCoords) {
+                var glTFPbrMetallicRoughness = {};
+                var glTFMaterial = {
+                    name: babylonPBRMaterial.name
+                };
+                var useMetallicRoughness = babylonPBRMaterial.isMetallicWorkflow();
+                if (babylonPBRMaterial) {
+                    if (useMetallicRoughness) {
+                        glTFPbrMetallicRoughness.baseColorFactor = [
+                            babylonPBRMaterial.albedoColor.r,
+                            babylonPBRMaterial.albedoColor.g,
+                            babylonPBRMaterial.albedoColor.b,
+                            babylonPBRMaterial.alpha
+                        ];
+                        if (babylonPBRMaterial.metallic != null) {
+                            if (babylonPBRMaterial.metallic !== 1) {
+                                glTFPbrMetallicRoughness.metallicFactor = babylonPBRMaterial.metallic;
+                            }
+                        }
+                        if (babylonPBRMaterial.roughness != null) {
+                            if (babylonPBRMaterial.roughness !== 1) {
+                                glTFPbrMetallicRoughness.roughnessFactor = babylonPBRMaterial.roughness;
+                            }
+                        }
+                    }
+                    else {
+                        var diffuseColor = babylonPBRMaterial.albedoColor || BABYLON.Color3.Black();
+                        var specularColor = babylonPBRMaterial.reflectionColor || BABYLON.Color3.Black();
+                        var diffusePerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(diffuseColor);
+                        var specularPerceivedBrightness = _GLTFMaterial.GetPerceivedBrightness(specularColor);
+                        var oneMinusSpecularStrength = 1 - _GLTFMaterial.GetMaxComponent(babylonPBRMaterial.reflectionColor);
+                        var metallic = _GLTFMaterial.SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
+                        var glossiness = babylonPBRMaterial.microSurface || 0;
+                        var baseColorFromDiffuse = diffuseColor.scale(oneMinusSpecularStrength / (1.0 - this.dielectricSpecular.r) / Math.max(1 - metallic, this.epsilon));
+                        var baseColorFromSpecular = specularColor.subtract(this.dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic, this.epsilon));
+                        var baseColor = BABYLON.Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
+                        baseColor = baseColor.clampToRef(0, 1, baseColor);
+                        glTFPbrMetallicRoughness.baseColorFactor = [
+                            baseColor.r,
+                            baseColor.g,
+                            baseColor.b,
+                            babylonPBRMaterial.alpha
+                        ];
+                        if (metallic !== 1) {
+                            glTFPbrMetallicRoughness.metallicFactor = metallic;
+                        }
+                        if (glossiness) {
+                            glTFPbrMetallicRoughness.roughnessFactor = 1 - glossiness;
+                        }
+                    }
+                    if (babylonPBRMaterial.backFaceCulling) {
+                        if (!babylonPBRMaterial.twoSidedLighting) {
+                            BABYLON.Tools.Warn(babylonPBRMaterial.name + ": Back-face culling enabled and two-sided lighting disabled is not supported in glTF.");
+                        }
+                        glTFMaterial.doubleSided = true;
+                    }
+                    if (hasTextureCoords) {
+                        if (babylonPBRMaterial.albedoTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.albedoTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture) {
+                                glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.bumpTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.bumpTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture) {
+                                glTFMaterial.normalTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.ambientTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.ambientTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture) {
+                                var occlusionTexture = {
+                                    index: glTFTexture.index
+                                };
+                                glTFMaterial.occlusionTexture = occlusionTexture;
+                                if (babylonPBRMaterial.ambientTextureStrength) {
+                                    occlusionTexture.strength = babylonPBRMaterial.ambientTextureStrength;
+                                }
+                            }
+                        }
+                        if (babylonPBRMaterial.emissiveTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.emissiveTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture != null) {
+                                glTFMaterial.emissiveTexture = glTFTexture;
+                            }
+                        }
+                        if (babylonPBRMaterial.metallicTexture) {
+                            var glTFTexture = _GLTFMaterial.ExportTexture(babylonPBRMaterial.metallicTexture, mimeType, images, textures, imageData);
+                            if (glTFTexture != null) {
+                                glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
+                            }
+                        }
+                    }
+                    if (!babylonPBRMaterial.emissiveColor.equalsFloats(0.0, 0.0, 0.0)) {
+                        glTFMaterial.emissiveFactor = babylonPBRMaterial.emissiveColor.asArray();
+                    }
+                    if (babylonPBRMaterial.transparencyMode != null) {
+                        var alphaMode = _GLTFMaterial.GetAlphaMode(babylonPBRMaterial);
+                        if (alphaMode !== "OPAQUE" /* OPAQUE */) {
+                            glTFMaterial.alphaMode = alphaMode;
+                            if (alphaMode === "BLEND" /* BLEND */) {
+                                glTFMaterial.alphaCutoff = babylonPBRMaterial.alphaCutOff;
+                            }
+                        }
+                    }
+                }
+                glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
+                materials.push(glTFMaterial);
+            };
+            /**
              * Extracts a texture from a Babylon texture into file data and glTF data.
              * @param babylonTexture - Babylon texture to extract.
              * @param mimeType - Mime Type of the babylonTexture.
@@ -1284,6 +1524,7 @@ var BABYLON;
              * Allows the maximum specular power to be defined for material calculations.
              */
             _GLTFMaterial.maxSpecularPower = 1024;
+            _GLTFMaterial.epsilon = 1e-6;
             return _GLTFMaterial;
         }());
         GLTF2._GLTFMaterial = _GLTFMaterial;
@@ -1292,22 +1533,6 @@ var BABYLON;
 
 //# sourceMappingURL=babylon.glTFMaterial.js.map
 
-
-(function universalModuleDefinition(root, factory) {
-                var f = factory();
-                if (root && root["BABYLON"]) {
-                    return;
-                }
-                
-    if(typeof exports === 'object' && typeof module === 'object')
-        module.exports = f;
-    else if(typeof define === 'function' && define.amd)
-        define(["BJSSerializers"], factory);
-    else if(typeof exports === 'object')
-        exports["BJSSerializers"] = f;
-    else {
-        root["BABYLON"] = f;
-    }
-})(this, function() {
+    
     return BABYLON;
 });

File diff suppressed because it is too large
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


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

@@ -1,258 +1,10 @@
 /// <reference types="babylonjs"/>
+/// <reference types="babylonjs-gltf2interface"/>
 
 
 declare module 'babylonjs-serializers' { 
     export = BABYLON; 
 }
-declare module BABYLON.GLTF2 {
-    const enum AccessorComponentType {
-        BYTE = 5120,
-        UNSIGNED_BYTE = 5121,
-        SHORT = 5122,
-        UNSIGNED_SHORT = 5123,
-        UNSIGNED_INT = 5125,
-        FLOAT = 5126,
-    }
-    const enum AccessorType {
-        SCALAR = "SCALAR",
-        VEC2 = "VEC2",
-        VEC3 = "VEC3",
-        VEC4 = "VEC4",
-        MAT2 = "MAT2",
-        MAT3 = "MAT3",
-        MAT4 = "MAT4",
-    }
-    const enum AnimationChannelTargetPath {
-        TRANSLATION = "translation",
-        ROTATION = "rotation",
-        SCALE = "scale",
-        WEIGHTS = "weights",
-    }
-    const enum AnimationSamplerInterpolation {
-        LINEAR = "LINEAR",
-        STEP = "STEP",
-        CUBICSPLINE = "CUBICSPLINE",
-    }
-    const enum CameraType {
-        PERSPECTIVE = "perspective",
-        ORTHOGRAPHIC = "orthographic",
-    }
-    const enum ImageMimeType {
-        JPEG = "image/jpeg",
-        PNG = "image/png",
-    }
-    const enum MaterialAlphaMode {
-        OPAQUE = "OPAQUE",
-        MASK = "MASK",
-        BLEND = "BLEND",
-    }
-    const enum MeshPrimitiveMode {
-        POINTS = 0,
-        LINES = 1,
-        LINE_LOOP = 2,
-        LINE_STRIP = 3,
-        TRIANGLES = 4,
-        TRIANGLE_STRIP = 5,
-        TRIANGLE_FAN = 6,
-    }
-    const enum TextureMagFilter {
-        NEAREST = 9728,
-        LINEAR = 9729,
-    }
-    const enum TextureMinFilter {
-        NEAREST = 9728,
-        LINEAR = 9729,
-        NEAREST_MIPMAP_NEAREST = 9984,
-        LINEAR_MIPMAP_NEAREST = 9985,
-        NEAREST_MIPMAP_LINEAR = 9986,
-        LINEAR_MIPMAP_LINEAR = 9987,
-    }
-    const enum TextureWrapMode {
-        CLAMP_TO_EDGE = 33071,
-        MIRRORED_REPEAT = 33648,
-        REPEAT = 10497,
-    }
-    interface IProperty {
-        extensions?: {
-            [key: string]: any;
-        };
-        extras?: any;
-    }
-    interface IChildRootProperty extends IProperty {
-        name?: string;
-    }
-    interface IAccessorSparseIndices extends IProperty {
-        bufferView: number;
-        byteOffset?: number;
-        componentType: AccessorComponentType;
-    }
-    interface IAccessorSparseValues extends IProperty {
-        bufferView: number;
-        byteOffset?: number;
-    }
-    interface IAccessorSparse extends IProperty {
-        count: number;
-        indices: IAccessorSparseIndices;
-        values: IAccessorSparseValues;
-    }
-    interface IAccessor extends IChildRootProperty {
-        bufferView?: number;
-        byteOffset?: number;
-        componentType: AccessorComponentType;
-        normalized?: boolean;
-        count: number;
-        type: AccessorType;
-        max?: number[];
-        min?: number[];
-        sparse?: IAccessorSparse;
-    }
-    interface IAnimationChannel extends IProperty {
-        sampler: number;
-        target: IAnimationChannelTarget;
-    }
-    interface IAnimationChannelTarget extends IProperty {
-        node: number;
-        path: AnimationChannelTargetPath;
-    }
-    interface IAnimationSampler extends IProperty {
-        input: number;
-        interpolation?: AnimationSamplerInterpolation;
-        output: number;
-    }
-    interface IAnimation extends IChildRootProperty {
-        channels: IAnimationChannel[];
-        samplers: IAnimationSampler[];
-    }
-    interface IAsset extends IChildRootProperty {
-        copyright?: string;
-        generator?: string;
-        version: string;
-        minVersion?: string;
-    }
-    interface IBuffer extends IChildRootProperty {
-        uri?: string;
-        byteLength: number;
-    }
-    interface IBufferView extends IChildRootProperty {
-        buffer: number;
-        byteOffset?: number;
-        byteLength: number;
-        byteStride?: number;
-    }
-    interface ICameraOrthographic extends IProperty {
-        xmag: number;
-        ymag: number;
-        zfar: number;
-        znear: number;
-    }
-    interface ICameraPerspective extends IProperty {
-        aspectRatio: number;
-        yfov: number;
-        zfar: number;
-        znear: number;
-    }
-    interface ICamera extends IChildRootProperty {
-        orthographic?: ICameraOrthographic;
-        perspective?: ICameraPerspective;
-        type: CameraType;
-    }
-    interface IImage extends IChildRootProperty {
-        uri?: string;
-        mimeType?: ImageMimeType;
-        bufferView?: number;
-    }
-    interface IMaterialNormalTextureInfo extends ITextureInfo {
-        scale?: number;
-    }
-    interface IMaterialOcclusionTextureInfo extends ITextureInfo {
-        strength?: number;
-    }
-    interface IMaterialPbrMetallicRoughness {
-        baseColorFactor?: number[];
-        baseColorTexture?: ITextureInfo;
-        metallicFactor?: number;
-        roughnessFactor?: number;
-        metallicRoughnessTexture?: ITextureInfo;
-    }
-    interface IMaterial extends IChildRootProperty {
-        pbrMetallicRoughness?: IMaterialPbrMetallicRoughness;
-        normalTexture?: IMaterialNormalTextureInfo;
-        occlusionTexture?: IMaterialOcclusionTextureInfo;
-        emissiveTexture?: ITextureInfo;
-        emissiveFactor?: number[];
-        alphaMode?: MaterialAlphaMode;
-        alphaCutoff?: number;
-        doubleSided?: boolean;
-    }
-    interface IMeshPrimitive extends IProperty {
-        attributes: {
-            [name: string]: number;
-        };
-        indices?: number;
-        material?: number;
-        mode?: MeshPrimitiveMode;
-        targets?: {
-            [name: string]: number;
-        }[];
-    }
-    interface IMesh extends IChildRootProperty {
-        primitives: IMeshPrimitive[];
-        weights?: number[];
-    }
-    interface INode extends IChildRootProperty {
-        camera?: number;
-        children?: number[];
-        skin?: number;
-        matrix?: number[];
-        mesh?: number;
-        rotation?: number[];
-        scale?: number[];
-        translation?: number[];
-        weights?: number[];
-    }
-    interface ISampler extends IChildRootProperty {
-        magFilter?: TextureMagFilter;
-        minFilter?: TextureMinFilter;
-        wrapS?: TextureWrapMode;
-        wrapT?: TextureWrapMode;
-    }
-    interface IScene extends IChildRootProperty {
-        nodes: number[];
-    }
-    interface ISkin extends IChildRootProperty {
-        inverseBindMatrices?: number;
-        skeleton?: number;
-        joints: number[];
-    }
-    interface ITexture extends IChildRootProperty {
-        sampler?: number;
-        source: number;
-    }
-    interface ITextureInfo {
-        index: number;
-        texCoord?: number;
-    }
-    interface IGLTF extends IProperty {
-        accessors?: IAccessor[];
-        animations?: IAnimation[];
-        asset: IAsset;
-        buffers?: IBuffer[];
-        bufferViews?: IBufferView[];
-        cameras?: ICamera[];
-        extensionsUsed?: string[];
-        extensionsRequired?: string[];
-        images?: IImage[];
-        materials?: IMaterial[];
-        meshes?: IMesh[];
-        nodes?: INode[];
-        samplers?: ISampler[];
-        scene?: number;
-        scenes?: IScene[];
-        skins?: ISkin[];
-        textures?: ITexture[];
-    }
-}
-
 
 declare module BABYLON {
     class OBJExport {
@@ -558,6 +310,7 @@ declare module BABYLON.GLTF2 {
          * Allows the maximum specular power to be defined for material calculations.
          */
         private static maxSpecularPower;
+        private static epsilon;
         /**
          * Gets the materials from a Babylon scene and converts them to glTF materials.
          * @param scene
@@ -575,6 +328,18 @@ declare module BABYLON.GLTF2 {
             };
         }, hasTextureCoords: boolean): void;
         /**
+         * Makes a copy of the glTF material without the texture parameters.
+         * @param originalMaterial - original glTF material.
+         * @returns glTF material without texture parameters
+         */
+        static StripTexturesFromMaterial(originalMaterial: IMaterial): IMaterial;
+        /**
+         * Specifies if the material has any texture parameters present.
+         * @param material - glTF Material.
+         * @returns boolean specifying if texture parameters are present
+         */
+        static HasTexturesPresent(material: IMaterial): boolean;
+        /**
          * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
          * @param babylonStandardMaterial
          * @returns - glTF Metallic Roughness Material representation
@@ -627,6 +392,35 @@ declare module BABYLON.GLTF2 {
             };
         }, hasTextureCoords: boolean): void;
         /**
+         * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
+         * @link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-bjs/js/babylon.pbrUtilities.js
+         * @param color - Color source to calculate brightness from.
+         * @returns number representing the perceived brightness, or zero if color is undefined.
+         */
+        static GetPerceivedBrightness(color: Color3): number;
+        /**
+         * Returns the maximum color component value.
+         * @param color
+         * @returns maximum color component value, or zero if color is null or undefined.
+         */
+        static GetMaxComponent(color: Color3): number;
+        /**
+         * Converts a Babylon PBR Metallic Roughness Material to a glTF Material.
+         * @param babylonPBRMaterial - BJS PBR Metallic Roughness Material.
+         * @param mimeType - mime type to use for the textures.
+         * @param images - array of glTF image interfaces.
+         * @param textures - array of glTF texture interfaces.
+         * @param materials - array of glTF material interfaces.
+         * @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.
+         */
+        static ConvertPBRMaterial(babylonPBRMaterial: PBRMaterial, mimeType: ImageMimeType, images: IImage[], textures: ITexture[], materials: IMaterial[], imageData: {
+            [fileName: string]: {
+                data: Uint8Array;
+                mimeType: ImageMimeType;
+            };
+        }, hasTextureCoords: boolean): void;
+        /**
          * Extracts a texture from a Babylon texture into file data and glTF data.
          * @param babylonTexture - Babylon texture to extract.
          * @param mimeType - Mime Type of the babylonTexture.

+ 4 - 1
dist/preview release/serializers/package.json

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

+ 12 - 121
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 7238,
+  "errors": 7220,
   "babylon.typedoc.json": {
-    "errors": 7238,
+    "errors": 7220,
     "AnimationKeyInterpolation": {
       "Enumeration": {
         "Comments": {
@@ -8113,50 +8113,6 @@
         }
       }
     },
-    "ConvolutionPostProcess": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Property": {
-        "kernel": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "EdgeDetect0Kernel": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "EdgeDetect1Kernel": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "EdgeDetect2Kernel": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "EmbossKernel": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "GaussianKernel": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "SharpenKernel": {
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      }
-    },
     "CubeTexture": {
       "Class": {
         "Comments": {
@@ -8841,6 +8797,11 @@
             "NotCamelCase": true
           }
         },
+        "ChromaticAberrationPostProcessId": {
+          "Naming": {
+            "NotCamelCase": true
+          }
+        },
         "CopyBackPostProcessId": {
           "Naming": {
             "NotCamelCase": true
@@ -8870,6 +8831,11 @@
           "Naming": {
             "NotCamelCase": true
           }
+        },
+        "SharpenPostProcessId": {
+          "Naming": {
+            "NotCamelCase": true
+          }
         }
       }
     },
@@ -10010,38 +9976,6 @@
             }
           }
         },
-        "bindFramebuffer": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "texture": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "faceIndex": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "requiredWidth": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "requiredHeight": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "forceFullscreenViewport": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
         "bindSamplers": {
           "Comments": {
             "MissingText": true
@@ -14243,13 +14177,6 @@
             "MissingText": true
           }
         }
-      },
-      "Method": {
-        "handleButtonChange": {
-          "Naming": {
-            "NotUnderscoreCamelCase": true
-          }
-        }
       }
     },
     "GenericController": {
@@ -14269,13 +14196,6 @@
             "MissingText": true
           }
         }
-      },
-      "Method": {
-        "handleButtonChange": {
-          "Naming": {
-            "NotUnderscoreCamelCase": true
-          }
-        }
       }
     },
     "GenericPad": {
@@ -20448,13 +20368,6 @@
             "MissingText": true
           }
         }
-      },
-      "Method": {
-        "handleButtonChange": {
-          "Naming": {
-            "NotUnderscoreCamelCase": true
-          }
-        }
       }
     },
     "OimoJSPlugin": {
@@ -25347,11 +25260,6 @@
             "MissingText": true
           }
         },
-        "invertYAxis": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
         "name": {
           "Comments": {
             "MissingText": true
@@ -37403,13 +37311,6 @@
             "MissingText": true
           }
         }
-      },
-      "Method": {
-        "handleButtonChange": {
-          "Naming": {
-            "NotUnderscoreCamelCase": true
-          }
-        }
       }
     },
     "VolumetricLightScatteringPostProcess": {
@@ -37505,11 +37406,6 @@
         }
       },
       "Method": {
-        "handleButtonChange": {
-          "Naming": {
-            "NotUnderscoreCamelCase": true
-          }
-        },
         "initControllerMesh": {
           "Comments": {
             "MissingText": true
@@ -37615,11 +37511,6 @@
         }
       },
       "Method": {
-        "handleButtonChange": {
-          "Naming": {
-            "NotUnderscoreCamelCase": true
-          }
-        },
         "lerpAxisTransform": {
           "Naming": {
             "NotUnderscoreCamelCase": true

File diff suppressed because it is too large
+ 70 - 70
dist/preview release/viewer/babylon.viewer.js


File diff suppressed because it is too large
+ 1077 - 259
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-viewer",
     "description": "A simple-to-use viewer based on BabylonJS to display 3D elements natively",
-    "version": "3.2.0-alpha8",
+    "version": "3.2.0-alphaB",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,9 +27,6 @@
         "viewer"
     ],
     "license": "Apache-2.0",
-    "peerDependencies": {
-        "babylonjs": ">=3.2.0-alpha"
-    },
     "engines": {
         "node": "*"
     }

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

@@ -6,7 +6,7 @@
 - Improved building process: We now run a full visual validation test for each pull request. Furthermore, code comments and what's new updates are now mandatory ([sebavan](https://github.com/sebavan))
 - Introduced texture binding atlas. This optimization allows the engine to reuse texture bindings instead of rebinding textures when they are not on constant sampler indexes ([deltakosh](https://github.com/deltakosh))
 - New [AnimationGroup class](http://doc.babylonjs.com/how_to/group) to control simultaneously multiple animations with different targets ([deltakosh](https://github.com/deltakosh))
-- `WebVRCamera` now supports GearVR ([brianzinn](https://github.com/brianzinn))
+- `WebVRCamera` add basic support for Daydream and Gear VR ([brianzinn](https://github.com/brianzinn))
 - New glTF [serializer](https://github.com/BabylonJS/Babylon.js/tree/master/serializers/src/glTF/2.0). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))
 - Babylon.js now uses Promises in addition to callbacks. We created several `xxxAsync` functions all over the framework (`SceneLoader.AppendAsync` for instance, which returns a Promise). A polyfill is also integrated to support older browsers ([deltakosh](https://github.com/deltakosh))
 - Introduced [Projection Texture on SpotLight](http://doc.babylonjs.com/babylon101/lights#projection-texture) ([lostink](https://github.com/lostink))
@@ -14,12 +14,13 @@
 - Added [VideoDome](http://doc.babylonjs.com/how_to/360videodome) class to easily support 360 videos ([DavidHGillen](https://github.com/DavidHGillen))
 - Added [GlowLayer](https://doc.babylonjs.com/how_to/glow_layer) to easily support glow from emissive materials ([sebavan](https://github.com/sebavan))
 - New [AssetContainer](http://doc.babylonjs.com/how_to/how_to_use_assetcontainer) Class and loading methods ([trevordev](https://github.com/trevordev))
-- Added depth of field effect to the default pipeline ([trevordev](https://github.com/trevordev))
-- Particle System SubEmitters- Spawn new Sub emitter when particles dies and Cone/Sphere shapes emitters ([IbraheemOsama](https://github.com/IbraheemOsama))
+- Added depth of field, MSAA, sharpening, grain and chromatic aberration effect to the default pipeline ([trevordev](https://github.com/trevordev))
 
 ## Updates
 
 - Tons of functions and classes received the code comments they deserved (All the community)
+- New `AnimationPropertiesOverride` class used to simplify setting animation properties on child animations. [Documentation](http://doc.babylonjs.com/babylon101/animations#overriding-properties) ([deltakosh](https://github.com/deltakosh))
+- New `Texture.UseSerializedUrlIfAny` static property to let textures serialize complete URL instead of using side by side loading ([deltakosh](https://github.com/deltakosh))
 - Added `particleSystem.reset()` to clear a particle system ([deltakosh](https://github.com/deltakosh))
 - Added support for all RGBA orders (BGR, RGB, etc..) for the DDS loader ([deltakosh](https://github.com/deltakosh))
 - Improved [SceneOptimizer](http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer) to provide better adaptability ([deltakosh](https://github.com/deltakosh))
@@ -51,7 +52,7 @@
 - (Viewer) Scene Optimizer intergrated in viewer. ([RaananW](https://github.com/RaananW))
 - (Viewer) The viewer supports custom shaders in the configuration. ([RaananW](https://github.com/RaananW))
 - Documented PostProcessRenderEffect, DefaultRenderingPipeline, BlurPostProcess, DepthOfFieldEffect, PostProcess, PostProcessManager, Effect classes ([trevordev](https://github.com/trevordev))
-- SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie)) 
+- SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie))
 - SPS particle parenting feature ([jbousquie](https://github.com/jbousquie))
 - (Viewer) Introducing the viewer labs - testing new features. ([RaananW](https://github.com/RaananW))
 - KeepAssets class and AssetContainer.moveAllFromScene ([HoloLite](http://www.html5gamedevs.com/profile/28694-hololite/) [trevordev](https://github.com/trevordev))
@@ -78,6 +79,11 @@
 - (Viewer) XHR requests not use Tools.LoadFile and are disposed correctly - [#3671](https://github.com/BabylonJS/Babylon.js/issues/3671) ([RaananW](https://github.com/RaananW))
 - Added `Tools.WorkerPool` class for web worker management. ([bghgary](https://github.com/bghgary))
 - Support depth maps for multiple active cameras for post processes like depth of field ([trevordev](https://github.com/trevordev))
+- Integrates depth texture support in the engine ([sebavan](https://github.com/sebavan))
+- NPM package now has a dependency system, updated during build. ([RaananW](https://github.com/RaananW))
+- WebVRExperienceHelper will create an empty controller model so that controller interactions can be used while the actual model is still loading ([trevordev](https://github.com/trevordev))
+- Default fragment shader will clamp negative values to avoid underflow, webVR post processing will render to eye texture size ([trevordev](https://github.com/trevordev))
+- Supports Environment Drag and Drop in Sandbox ([sebavan](https://github.com/sebavan))
 
 ## Bug fixes
 
@@ -88,6 +94,13 @@
 - Fixed a bug when calling load on an empty assets manager - [#3739](https://github.com/BabylonJS/Babylon.js/issues/3739). ([RaananW](https://github.com/RaananW))
 - Enabling teleportation in the vr helper class caused a redundant post process to be added ([trevordev](https://github.com/trevordev))
 - (Viewer) Fixed a bug where loading another mesh positioned it incorrectly ([RaananW](https://github.com/RaananW))
+- Scale vr controllers by deviceScale when it is set in VRExperienceHelper ([trevordev](https://github.com/trevordev))
+- (Viewer) Disabling templates now work correctly ([RaananW](https://github.com/RaananW))
+- AMD "define" declaration is no longer anonymous ([RaananW](https://github.com/RaananW))
+- Collision worker didn't initialize instanced meshes correctly - [#3819](https://github.com/BabylonJS/Babylon.js/issues/3819) ([RaananW](https://github.com/RaananW))
+- postMessage calls in webworkers were fixed. ([RaananW](https://github.com/RaananW))
+- Fixed WebCam Texture on Firefox and Edge - [#3825](https://github.com/BabylonJS/Babylon.js/issues/3825) ([sebavan](https://github.com/sebavan))
+- Add onLoadObservable on VideoTexture - [#3845](https://github.com/BabylonJS/Babylon.js/issues/3845) ([sebavan](https://github.com/sebavan))
 
 ## Breaking changes
 

+ 17 - 2
gui/src/advancedDynamicTexture.ts

@@ -28,6 +28,7 @@ module BABYLON.GUI {
         private _fullscreenViewport = new Viewport(0, 0, 1, 1);
         private _idealWidth = 0;
         private _idealHeight = 0;
+        private _useSmallestIdeal: boolean = false;
         private _renderAtIdealSize = false;
         private _focusedControl: Nullable<IFocusableControl>;
         private _blockNextFocusCheck = false;
@@ -88,6 +89,20 @@ module BABYLON.GUI {
             this._rootContainer._markAllAsDirty();
         }
 
+        public get useSmallestIdeal(): boolean {
+            return this._useSmallestIdeal;
+        }
+
+        public set useSmallestIdeal(value: boolean) {
+            if (this._useSmallestIdeal === value) {
+                return;
+            }
+
+            this._useSmallestIdeal = value;
+            this.markAsDirty();
+            this._rootContainer._markAllAsDirty();
+        }
+
         public get renderAtIdealSize(): boolean {
             return this._renderAtIdealSize;
         }
@@ -381,8 +396,8 @@ module BABYLON.GUI {
             var textureSize = this.getSize();
 
             if (this._isFullscreen) {
-                x = x * ((textureSize.width / this._renderScale) / engine.getRenderWidth());
-                y = y * ((textureSize.height / this._renderScale) / engine.getRenderHeight());
+                x = x * (textureSize.width / engine.getRenderWidth());
+                y = y * (textureSize.height / engine.getRenderHeight());
             }
 
             if (this._capturingControl[pointerId]) {

+ 2 - 2
gui/src/controls/button.ts

@@ -84,12 +84,12 @@ module BABYLON.GUI {
             return true;
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
             if (this.pointerUpAnimation) {
                 this.pointerUpAnimation();
             }
 
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
         }        
 
         // Statics

+ 2 - 2
gui/src/controls/colorpicker.ts

@@ -407,11 +407,11 @@ module BABYLON.GUI {
             super._onPointerMove(target, coordinates);
         }
 
-        public _onPointerUp (target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
+        public _onPointerUp (target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
             this._pointerIsDown = false;
             
             delete this._host._capturingControl[pointerId];
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
         }     
     }    
 }

+ 2 - 0
gui/src/controls/container.ts

@@ -80,6 +80,8 @@ module BABYLON.GUI {
                 control.parent = null;
             }
 
+            control.linkWithMesh(null);
+
             this._markAsDirty();
             return this;
         }

+ 47 - 9
gui/src/controls/control.ts

@@ -36,6 +36,7 @@ module BABYLON.GUI {
         private _transformMatrix = Matrix2D.Identity();
         protected _invertTransformMatrix = Matrix2D.Identity();
         protected _transformedPosition = Vector2.Zero();
+        private _onlyMeasureMode = false;
         private _isMatrixDirty = true;
         private _cachedOffsetX: number;
         private _cachedOffsetY: number;
@@ -91,6 +92,12 @@ module BABYLON.GUI {
         public onPointerUpObservable = new Observable<Vector2WithInfo>();
 
         /**
+        * An event triggered when a control is clicked on
+        * @type {BABYLON.Observable}
+        */
+        public onPointerClickObservable = new Observable<Vector2WithInfo>();
+
+        /**
         * An event triggered when pointer enters the control
         * @type {BABYLON.Observable}
         */
@@ -545,7 +552,9 @@ module BABYLON.GUI {
 
         public linkWithMesh(mesh: Nullable<AbstractMesh>): void {
             if (!this._host || this._root && this._root !== this._host._rootContainer) {
-                Tools.Error("Cannot link a control to a mesh if the control is not at root level");
+                if (mesh) {
+                    Tools.Error("Cannot link a control to a mesh if the control is not at root level");
+                }
                 return;
             }
 
@@ -556,17 +565,36 @@ module BABYLON.GUI {
                     this._host._linkedControls.splice(index, 1);
                 }
                 return;
+            } else if (!mesh) {
+                return;
             }
 
             this.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
             this.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
             this._linkedMesh = mesh;
+            this._onlyMeasureMode = true;
             this._host._linkedControls.push(this);
         }
 
         public _moveToProjectedPosition(projectedPosition: Vector3): void {
-            this.left = ((projectedPosition.x + this._linkOffsetX.getValue(this._host)) - this._currentMeasure.width / 2) + "px";
-            this.top = ((projectedPosition.y + this._linkOffsetY.getValue(this._host)) - this._currentMeasure.height / 2) + "px";
+            let oldLeft = this._left.getValue(this._host);
+            let oldTop = this._top.getValue(this._host);
+            
+            var newLeft = ((projectedPosition.x + this._linkOffsetX.getValue(this._host)) - this._currentMeasure.width / 2);
+            var newTop = ((projectedPosition.y + this._linkOffsetY.getValue(this._host)) - this._currentMeasure.height / 2);
+
+            if (this._left.ignoreAdaptiveScaling && this._top.ignoreAdaptiveScaling) {
+                if (Math.abs(newLeft - oldLeft) < 0.5) {
+                    newLeft = oldLeft;
+                }
+
+                if (Math.abs(newTop - oldTop) < 0.5) {
+                    newTop = oldTop;
+                }                
+            }
+
+            this.left = newLeft + "px";
+            this.top = newTop + "px";
 
             this._left.ignoreAdaptiveScaling = true;
             this._top.ignoreAdaptiveScaling = true;
@@ -695,6 +723,11 @@ module BABYLON.GUI {
             // Transform
             this._transform(context);
 
+            if (this._onlyMeasureMode) {
+                this._onlyMeasureMode = false;
+                return false; // We do not want rendering for this frame as they are measure dependant information that need to be gathered
+            }
+
             // Clip
             this._clip(context);
             context.clip();
@@ -918,22 +951,26 @@ module BABYLON.GUI {
             return true;
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
             this._downCount = 0;
 
             delete this._downPointerIds[pointerId];
 
-            var canNotify: boolean = this.onPointerUpObservable.notifyObservers(new Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
+            var canNotifyClick: boolean = notifyClick;
+			if (notifyClick && this._enterCount > 0) {
+				canNotifyClick = this.onPointerClickObservable.notifyObservers(new Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
+			}
+			var canNotify: boolean = this.onPointerUpObservable.notifyObservers(new Vector2WithInfo(coordinates, buttonIndex), -1, target, this);
 
-            if (canNotify && this.parent != null) this.parent._onPointerUp(target, coordinates, pointerId, buttonIndex);
+            if (canNotify && this.parent != null) this.parent._onPointerUp(target, coordinates, pointerId, buttonIndex, canNotifyClick);
         }
 
         public forcePointerUp(pointerId:Nullable<number> = null) {
             if(pointerId !== null){
-                this._onPointerUp(this, Vector2.Zero(), pointerId, 0);
+                this._onPointerUp(this, Vector2.Zero(), pointerId, 0, true);
             }else{
                 for(var key in this._downPointerIds){
-                    this._onPointerUp(this, Vector2.Zero(), +key as number, 0);
+                    this._onPointerUp(this, Vector2.Zero(), +key as number, 0, true);
                 }
             }
         }
@@ -965,7 +1002,7 @@ module BABYLON.GUI {
 
             if (type === BABYLON.PointerEventTypes.POINTERUP) {
                 if (this._host._lastControlDown[pointerId]) {
-                    this._host._lastControlDown[pointerId]._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex);
+                    this._host._lastControlDown[pointerId]._onPointerUp(this, this._dummyVector2, pointerId, buttonIndex, true);
                 }
                 delete this._host._lastControlDown[pointerId];
                 return true;
@@ -993,6 +1030,7 @@ module BABYLON.GUI {
             this.onPointerMoveObservable.clear();
             this.onPointerOutObservable.clear();
             this.onPointerUpObservable.clear();
+			this.onPointerClickObservable.clear();
 
             if (this._root) {
                 this._root.removeControl(this);

+ 2 - 2
gui/src/controls/inputText.ts

@@ -449,8 +449,8 @@ module BABYLON.GUI {
             return true;
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
         }
 
         public dispose() {

+ 2 - 2
gui/src/controls/slider.ts

@@ -287,11 +287,11 @@ module BABYLON.GUI {
             super._onPointerMove(target, coordinates);
         }
 
-        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number): void {
+        public _onPointerUp(target: Control, coordinates: Vector2, pointerId:number, buttonIndex: number, notifyClick: boolean): void {
             this._pointerIsDown = false;
 
             delete this._host._capturingControl[pointerId];
-            super._onPointerUp(target, coordinates, pointerId, buttonIndex);
+            super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
         }
     }
 }

+ 17 - 3
gui/src/valueAndUnit.ts

@@ -31,13 +31,27 @@ module BABYLON.GUI {
 
         public getValue(host: AdvancedDynamicTexture): number {
             if (host && !this.ignoreAdaptiveScaling && this.unit !== ValueAndUnit.UNITMODE_PERCENTAGE) {
+                var width: number = 0;
+                var height: number = 0;
 
-                if (host.idealWidth) { // horizontal
-                    return (this._value * host.getSize().width) / host.idealWidth;
+                if (host.idealWidth) {
+                    width = (this._value * host.getSize().width) / host.idealWidth;
+                }
+                
+                if (host.idealHeight) {
+                    height = (this._value * host.getSize().height) / host.idealHeight;
+                }
+
+                if (host.useSmallestIdeal && host.idealWidth && host.idealHeight) {
+                    return window.innerWidth < window.innerHeight ? width : height;
                 }
 
+                if (host.idealWidth) { // horizontal
+                    return width;
+                }
+                
                 if (host.idealHeight) { // vertical
-                    return (this._value * host.getSize().height) / host.idealHeight;
+                    return height;
                 }
             }
             return this._value;

+ 62 - 14
inspector/src/details/DetailPanel.ts

@@ -11,6 +11,9 @@
         private _detailRows : Array<PropertyLine> = [];
         // Store the sort direction of each header column
         private _sortDirection : SortDirection = {};
+        // The search bar
+        private _searchDetails : SearchBarDetails;
+        private _details : HTMLElement;
 
         constructor(dr? : Array<PropertyLine>) {
             super();
@@ -23,36 +26,72 @@
         }
 
         set details(detailsRow : Array<PropertyLine>) {
-            this.clean();   
+            this.clean();
+            //add the searchBar
+            this._addSearchBarDetails();
+            this._details = Helpers.CreateDiv('details', this._div);
             this._detailRows = detailsRow;
-            
             // Refresh HTML
             this.update();
         }
-        protected _build() {            
+
+        protected _build() {
             this._div.className = 'insp-details';
             this._div.id = 'insp-details';
-            
             // Create header row
             this._createHeaderRow();
             this._div.appendChild(this._headerRow);
             
-        }
+        } 
         
         /** Updates the HTML of the detail panel */
-        public update() {                 
-            this._sortDetails('name', 1);  
-            this._addDetails();
+        public update(_items?: Array<PropertyLine>) {            
+            this._sortDetails('name', 1);
+            // Check the searchbar
+            if (_items) {
+                this.cleanRow();
+                this._addSearchDetails(_items);
+                //console.log(_items);
+            } else {
+                this._addDetails();
+                //console.log("np");
+            }
+        }
+
+         /** Add the search bar for the details */
+        private _addSearchBarDetails() {
+            let searchDetails = Helpers.CreateDiv('searchbar-details', this._div);
+            // Create search bar
+            this._searchDetails = new SearchBarDetails(this);
+
+            searchDetails.appendChild(this._searchDetails.toHtml());
+            this._div.appendChild(searchDetails);
+        }
+
+        /** Search an element by name  */
+        public searchByName(searchName: string) {
+            let rows = [];
+            for (let row of this._detailRows) {
+                if(row.name.indexOf(searchName) >= 0){
+                    rows.push(row);
+                }
+            }
+            this.update(rows);
         }
 
         /** Add all lines in the html div. Does not sort them! */
         private _addDetails() {
-            let details = Helpers.CreateDiv('details', this._div);
             for (let row of this._detailRows) {
-                details.appendChild(row.toHtml());
+                this._details.appendChild(row.toHtml());
             }
         }
 
+        private _addSearchDetails(_items: Array<PropertyLine>) {
+            for (let row of _items) {
+                this._details.appendChild(row.toHtml());
+            }   
+        }
+
         /**
          * Sort the details row by comparing the given property of each row
          */
@@ -108,18 +147,27 @@
         /**
          * Removes all data in the detail panel but keep the header row
          */
-        public clean() {   
-                        
+        public clean() {         
             // Delete all details row
             for (let pline of this._detailRows) {
                 pline.dispose();
             }
-            
             Helpers.CleanDiv(this._div);
             // Header row
             this._div.appendChild(this._headerRow);
         }
 
+        /**
+         * Clean the rows only
+         */
+        public cleanRow() {           
+            // Delete all details row
+            for (let pline of this._detailRows) {
+                pline.dispose();
+            }
+            Helpers.CleanDiv(this._details);
+        }
+
         /** Overrides basicelement.dispose */
         public dispose() {
             // Delete all details row
@@ -139,7 +187,7 @@
 
                 // Column title - first letter in uppercase
                 let spanName = Inspector.DOCUMENT.createElement('span');
-                spanName.textContent = name.charAt(0).toUpperCase() + name.slice(1); 
+                spanName.textContent = name.charAt(0).toUpperCase() + name.slice(1);
                 
                 // sort direction
                 let spanDirection = Inspector.DOCUMENT.createElement('i');

+ 84 - 3
inspector/src/details/PropertyLine.ts

@@ -223,6 +223,8 @@ module INSPECTOR {
             if (this._parent) {
                 this._property.obj = this._parent.updateObject();
             }
+            
+            
             return this._property.value;
         }
 
@@ -319,6 +321,60 @@ module INSPECTOR {
                 this._rangeInput();
             } else {
                 this._valueDiv.childNodes[0].nodeValue = this._displayValueContent();
+
+            //Doing the Hexa convertion
+            if((this._property.type == "Color3" && this._children.length == 5 && this._children[1].value == true) || (this._property.type == "Color4" && this._children.length == 6 && this._children[1].value == true)){
+                if(this._children[0] != undefined &&  this._children[0].name == "hex"){
+                    let hexLineString = this._children[0].value;
+                    let rValue = (parseInt((hexLineString.slice(1,3)), 16)) * (1/255);
+                    let rValueRound = Math.round(100*rValue)/100 ;
+                    this.value.r = rValueRound;
+                    let gValue = (parseInt((hexLineString.slice(3,5)), 16)) * (1/255);
+                    let gValueRound = Math.round(100*gValue)/100 ;
+                    this.value.g = gValueRound;
+                    let bValue = (parseInt((hexLineString.slice(5,7)), 16)) * (1/255);
+                    let bValueRound = Math.round(100*bValue)/100 ;
+                    this.value.b = bValueRound;
+                        if(this._children[2].name == "a"){
+                            let aValue = (parseInt((hexLineString.slice(7,9)), 16)) * (1/255);
+                            let aValueRound = Math.round(100*aValue)/100;
+                            this.value.a = aValueRound;
+                        }
+                    }
+            }else if(this._property.type == "Color3" || this._property.type == "Color4"){
+                if(this._property.value.hex != undefined && this._property.value.hex != null){
+                    let hexLineInfos = [];
+                    let valHexR = ((this._property.value.r * 255)|0).toString(16);
+                    hexLineInfos.push(valHexR);
+                    if(valHexR == "0"){
+                        hexLineInfos.push("0");
+                    }
+                    let valHexG = ((this._property.value.g * 255)|0).toString(16);
+                    hexLineInfos.push(valHexG);
+                    if(valHexG == "0"){
+                        hexLineInfos.push("0");
+                    }
+                    let valHexB = ((this._property.value.b * 255)|0).toString(16);
+                    hexLineInfos.push(valHexB);
+                    if(valHexB == "0"){
+                        hexLineInfos.push("0");
+                    }
+                    if(this._property.value.a != undefined){
+                        let valHexA = ((this._property.value.a * 255)|0).toString(16);
+                        hexLineInfos.push(valHexA);
+                        if(valHexA == "0"){
+                            hexLineInfos.push("0");
+                        }
+                    }
+                    hexLineInfos.unshift("#");
+                    let hexLineString = hexLineInfos.join("");
+                    this._property.value.hex = hexLineString; 
+                    hexLineInfos.length = 0;
+                }
+
+            }
+            
+
             }
             for (let elem of this._elements) {
                 elem.update(this.value);
@@ -386,22 +442,47 @@ module INSPECTOR {
                 // if children does not exists, generate it
                 this._div.classList.toggle('unfolded');
                 if (this._children.length == 0) {
+                    
                     let objToDetail = this.value;
+                    
                     // Display all properties that are not functions
                     let propToDisplay = Helpers.GetAllLinesPropertiesAsString(objToDetail);
-
                     // special case for color3
                     if ((propToDisplay.indexOf('r') && propToDisplay.indexOf('g') && propToDisplay.indexOf('b')) == 0) {
                         propToDisplay.sort();
                     } else {
                         propToDisplay.sort().reverse();
                     }
-
                     for (let prop of propToDisplay) {
                         let infos = new Property(prop, this._property.value);
-                        let child = new PropertyLine(infos, this, this._level + PropertyLine._MARGIN_LEFT);
+                        let child = new PropertyLine(infos, this, this._level + PropertyLine._MARGIN_LEFT);                   
                         this._children.push(child);
                     }
+                    //Add the Hexa converter
+                    if ((propToDisplay.indexOf('r') && propToDisplay.indexOf('g') && propToDisplay.indexOf('b') && propToDisplay.indexOf('a')) == 0){
+                        let hexLineInfos = [];
+                        let hexLinePropCheck = new Property("hexEnable", this._property.value);
+                        hexLinePropCheck.value = false;
+                        let hexLineCheck = new PropertyLine(hexLinePropCheck, this, this._level + PropertyLine._MARGIN_LEFT);
+                        this._children.unshift(hexLineCheck);
+                        for (let prop of propToDisplay) {
+                                let infos = new Property(prop, this._property.value);
+                                let  valHex = ((infos.value * 255)|0).toString(16);
+                                hexLineInfos.push(valHex);
+                                if(valHex == "0"){
+                                    hexLineInfos.push("0");
+                                }
+                        }
+                        hexLineInfos.push("#");
+                        hexLineInfos.reverse();
+                        let hexLineString = hexLineInfos.join("");
+                        
+                        let hexLineProp = new Property("hex", this._property.value);
+                        hexLineProp.value = hexLineString;
+                        let hexLine = new PropertyLine(hexLineProp, this, this._level + PropertyLine._MARGIN_LEFT);
+                   
+                        this._children.unshift(hexLine);
+                    } 
                 }
                 // otherwise display it    
                 if (this._div.parentNode) {

+ 39 - 3
inspector/src/gui/SearchBar.ts

@@ -6,12 +6,12 @@ module INSPECTOR {
      */
     export class SearchBar extends BasicElement {
 
-        private _tab   : PropertyTab;
+        private _propTab   : PropertyTab;
         private _inputElement: HTMLInputElement;
 
         constructor(tab:PropertyTab) {
             super();
-            this._tab = tab;
+            this._propTab = tab;
             this._div.classList.add('searchbar');
             
             let filter = Inspector.DOCUMENT.createElement('i');
@@ -25,7 +25,43 @@ module INSPECTOR {
             
             this._inputElement.addEventListener('keyup', (evt : KeyboardEvent)=> {
                 let filter = this._inputElement.value;
-                this._tab.filter(filter);
+                this._propTab.filter(filter);
+            })
+        }
+
+        /** Delete all characters typped in the input element */
+        public reset() {
+            this._inputElement.value = '';
+        }
+
+        public update() {
+            // Nothing to update
+        }
+
+    }
+
+    export class SearchBarDetails extends BasicElement {
+
+        private _detailTab  : DetailPanel;
+        private _inputElement: HTMLInputElement;
+
+        constructor(tab:DetailPanel) {
+            super();
+            this._detailTab = tab;
+            this._div.classList.add('searchbar');
+            
+            let filter = Inspector.DOCUMENT.createElement('i');
+            filter.className = 'fa fa-search';
+            
+            this._div.appendChild(filter);
+            // Create input
+            this._inputElement = Inspector.DOCUMENT.createElement('input');
+            this._inputElement.placeholder = 'Filter by name...';
+            this._div.appendChild(this._inputElement);
+            
+            this._inputElement.addEventListener('keyup', (evt : KeyboardEvent)=> {
+                let filter = this._inputElement.value;
+                this._detailTab.searchByName(filter);
             })
         }
 

+ 17 - 6
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -33,7 +33,10 @@ module BABYLON.GLTF2.Extensions {
 
                     if (indexLOD !== 0) {
                         this._loadingNodeLOD = nodeLOD;
-                        this._loadNodeSignals[nodeLOD._index] = new Deferred<void>();
+
+                        if (!this._loadNodeSignals[nodeLOD._index]) {
+                            this._loadNodeSignals[nodeLOD._index] = new Deferred<void>();
+                        }
                     }
 
                     const promise = this._loader._loadNodeAsync("#/nodes/" + nodeLOD._index, nodeLOD).then(() => {
@@ -44,8 +47,11 @@ module BABYLON.GLTF2.Extensions {
 
                         if (indexLOD !== nodeLODs.length - 1) {
                             const nodeIndex = nodeLODs[indexLOD + 1]._index;
-                            this._loadNodeSignals[nodeIndex].resolve();
-                            delete this._loadNodeSignals[nodeIndex];
+
+                            if (this._loadNodeSignals[nodeIndex]) {
+                                this._loadNodeSignals[nodeIndex].resolve();
+                                delete this._loadNodeSignals[nodeIndex];
+                            }
                         }
                     });
 
@@ -77,14 +83,19 @@ module BABYLON.GLTF2.Extensions {
 
                     if (indexLOD !== 0) {
                         this._loadingMaterialLOD = materialLOD;
-                        this._loadMaterialSignals[materialLOD._index] = new Deferred<void>();
+
+                        if (!this._loadMaterialSignals[materialLOD._index]) {
+                            this._loadMaterialSignals[materialLOD._index] = new Deferred<void>();
+                        }
                     }
 
                     const promise = this._loader._loadMaterialAsync("#/materials/" + materialLOD._index, materialLOD, babylonMesh).then(() => {
                         if (indexLOD !== materialLODs.length - 1) {
                             const materialIndex = materialLODs[indexLOD + 1]._index;
-                            this._loadMaterialSignals[materialIndex].resolve();
-                            delete this._loadMaterialSignals[materialIndex];
+                            if (this._loadMaterialSignals[materialIndex]) {
+                                this._loadMaterialSignals[materialIndex].resolve();
+                                delete this._loadMaterialSignals[materialIndex];
+                            }
                         }
                     });
 

+ 3 - 2
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -706,8 +706,9 @@ module BABYLON.GLTF2 {
             };
 
             if (skin._loaded) {
-                assignSkeleton();
-                return skin._loaded;
+                return skin._loaded.then(() => {
+                    assignSkeleton();
+                });
             }
 
             // TODO: split into two parts so that bones are created before inverseBindMatricesData is loaded (for compiling materials).

+ 1 - 0
materialsLibrary/src/custom/babylon.customMaterial.ts

@@ -77,6 +77,7 @@ module BABYLON {
         public SAMPLER3DBGRMAP = false;
         public IMAGEPROCESSINGPOSTPROCESS = false;
         public EXPOSURE = false;
+        public GRAIN = false;
 
         constructor() {
             super();

+ 1 - 1
package.json

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

+ 10 - 1
sandbox/index.js

@@ -20,6 +20,7 @@ if (BABYLON.Engine.isSupported()) {
     var currentSkybox;
     var enableDebugLayer = false;
     var currentPluginName;
+    var skyboxPath = "Assets/environment.dds";
 
     canvas.addEventListener("contextmenu", function (evt) {
         evt.preventDefault();
@@ -98,7 +99,7 @@ if (BABYLON.Engine.isSupported()) {
 
         // Environment
         if (currentPluginName === "gltf") {
-            var hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData("Assets/environment.dds", currentScene);
+            var hdrTexture = BABYLON.CubeTexture.CreateFromPrefilteredData(skyboxPath, currentScene);
             currentSkybox = currentScene.createDefaultSkybox(hdrTexture, true, (currentScene.activeCamera.maxZ - currentScene.activeCamera.minZ) / 2, 0.3);
 
             // glTF assets use a +Z forward convention while the default camera faces +Z. Rotate the camera to look at the front of the asset.
@@ -147,6 +148,14 @@ if (BABYLON.Engine.isSupported()) {
     };
 
     filesInput = new BABYLON.FilesInput(engine, null, sceneLoaded, null, null, null, function () { BABYLON.Tools.ClearLogCache() }, null, sceneError);
+    filesInput.onProcessFileCallback = (function (file, name, extension) {
+        if (filesInput._filesToLoad && filesInput._filesToLoad.length === 1 && extension && extension.toLowerCase() === "dds") {
+            BABYLON.FilesInput.FilesToLoad[name] = file;
+            skyboxPath = "file:" + file.correctName;
+            return false;
+        }
+        return true;
+    }).bind(this);
     filesInput.monitorElementForDragNDrop(canvas);
 
     window.addEventListener("keydown", function (evt) {

+ 43 - 32
serializers/src/glTF/2.0/babylon.glTFExporter.ts

@@ -114,7 +114,7 @@ module BABYLON.GLTF2 {
             this.materials = new Array<IMaterial>();
             this.textures = new Array<ITexture>();
             this.imageData = {};
-            this.convertToRightHandedSystem = !this.babylonScene.useRightHandedSystem;
+            this.convertToRightHandedSystem = this.babylonScene.useRightHandedSystem ? false : true;
 
             if (options) {
                 this.options = options;
@@ -268,7 +268,6 @@ module BABYLON.GLTF2 {
                 }
                 else {
                     Tools.Warn("Unsupported Vertex Buffer Type: " + vertexBufferKind);
-                    
                 }
 
                 for (let i = 0; i < vector.length; ++i) {
@@ -498,11 +497,12 @@ module BABYLON.GLTF2 {
          * @param babylonMesh - Babylon mesh used as the source for the transformation data.
          */
         private setNodeTransformation(node: INode, babylonMesh: AbstractMesh): void {
-            if (!(babylonMesh.position.x === 0 && babylonMesh.position.y === 0 && babylonMesh.position.z === 0)) {
+            
+            if (!babylonMesh.position.equalsToFloats(0, 0, 0)) {
                 node.translation = this.convertToRightHandedSystem ? _Exporter.GetRightHandedVector3(babylonMesh.position).asArray() : babylonMesh.position.asArray();
             }
 
-            if (!(babylonMesh.scaling.x === 1 && babylonMesh.scaling.y === 1 && babylonMesh.scaling.z === 1)) {
+            if (!babylonMesh.scaling.equalsToFloats(1, 1, 1)) {
                 node.scale = babylonMesh.scaling.asArray();
             }
 
@@ -629,6 +629,7 @@ module BABYLON.GLTF2 {
                 }
 
                 if (babylonMesh.subMeshes) {
+                    let uvCoordsPresent = false;
                     // go through all mesh primitives (submeshes)
                     for (const submesh of babylonMesh.subMeshes) {
                         const meshPrimitive: IMeshPrimitive = { attributes: {} };
@@ -676,10 +677,12 @@ module BABYLON.GLTF2 {
                                                     }
                                                     case VertexBuffer.UVKind: {
                                                         meshPrimitive.attributes.TEXCOORD_0 = this.accessors.length - 1;
+                                                        uvCoordsPresent = true;
                                                         break;
                                                     }
                                                     case VertexBuffer.UV2Kind: {
                                                         meshPrimitive.attributes.TEXCOORD_1 = this.accessors.length - 1;
+                                                        uvCoordsPresent = true;
                                                         break;
                                                     }
                                                     default: {
@@ -697,13 +700,12 @@ module BABYLON.GLTF2 {
                                 this.accessors.push(accessor);
 
                                 meshPrimitive.indices = this.accessors.length - 1;
-
                             }
                         }
                         if (bufferMesh.material) {
-                            if (bufferMesh.material instanceof StandardMaterial || bufferMesh.material instanceof PBRMetallicRoughnessMaterial) {
-                                const materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
-                                meshPrimitive.material = materialIndex;
+                            let materialIndex: Nullable<number> = null;
+                            if (bufferMesh.material instanceof StandardMaterial || bufferMesh.material instanceof PBRMetallicRoughnessMaterial || bufferMesh.material instanceof PBRMaterial) {
+                                materialIndex = babylonMesh.getScene().materials.indexOf(bufferMesh.material);
                             }
                             else if (bufferMesh.material instanceof MultiMaterial) {
                                 const babylonMultiMaterial = bufferMesh.material as MultiMaterial;
@@ -711,16 +713,25 @@ module BABYLON.GLTF2 {
                                 const material = babylonMultiMaterial.subMaterials[submesh.materialIndex];
 
                                 if (material) {
-                                    const materialIndex = babylonMesh.getScene().materials.indexOf(material);
-                                    meshPrimitive.material = materialIndex;
+                                    materialIndex = babylonMesh.getScene().materials.indexOf(material);
                                 }
                             }
                             else {
                                 Tools.Warn("Material type " + bufferMesh.material.getClassName() + " for material " + bufferMesh.material.name + " is not yet implemented in glTF serializer.");
                             }
+                            if (materialIndex != null) {
+                                if (uvCoordsPresent || !_GLTFMaterial.HasTexturesPresent(this.materials[materialIndex])) {
+                                    meshPrimitive.material = materialIndex;
+                                }
+                                else {
+                                    // If no texture coordinate information is present, make a copy of the material without the textures to be glTF compliant.
+                                    const newMat = _GLTFMaterial.StripTexturesFromMaterial(this.materials[materialIndex]);
+                                    this.materials.push(newMat);
+                                    meshPrimitive.material = this.materials.length - 1;
+                                }
+                            }
                         }
                         mesh.primitives.push(meshPrimitive);
-
                     }
                 }
             }
@@ -749,32 +760,32 @@ module BABYLON.GLTF2 {
 
 
                 for (let i = 0; i < babylonMeshes.length; ++i) {
-                    if (this.options &&
-                        this.options.shouldExportMesh != undefined &&
-                        !this.options.shouldExportMesh(babylonMeshes[i])) {
-                        continue;
-                    }
-                    else {
-                        const babylonMesh = babylonMeshes[i];
-
-                        // Build Hierarchy with the node map.
-                        const glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
-                        const glTFNode = this.nodes[glTFNodeIndex];
-                        if (!babylonMesh.parent) {
+                    const babylonMesh = babylonMeshes[i];
+
+                    // Build Hierarchy with the node map.
+                    const glTFNodeIndex = this.nodeMap[babylonMesh.uniqueId];
+                    const glTFNode = this.nodes[glTFNodeIndex];
+                    if (!babylonMesh.parent) {
+                        if (this.options &&
+                            this.options.shouldExportMesh != undefined &&
+                            !this.options.shouldExportMesh(babylonMesh)) {
+                            Tools.Log("Omitting " + babylonMesh.name + " from scene.");
+                        }
+                        else {
                             scene.nodes.push(glTFNodeIndex);
                         }
 
-                        const directDescendents = babylonMesh.getDescendants(true);
-                        if (!glTFNode.children && directDescendents && directDescendents.length) {
-                            glTFNode.children = [];
-                            for (let descendent of directDescendents) {
-                                glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
-                            }
-                        }
+                    }
 
-                        const mesh = { primitives: new Array<IMeshPrimitive>() };
-                        byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
+                    const directDescendents = babylonMesh.getDescendants(true);
+                    if (!glTFNode.children && directDescendents && directDescendents.length) {
+                        glTFNode.children = [];
+                        for (let descendent of directDescendents) {
+                            glTFNode.children.push(this.nodeMap[descendent.uniqueId]);
+                        }
                     }
+                    const mesh = { primitives: new Array<IMeshPrimitive>() };
+                    byteOffset = this.setPrimitiveAttributes(mesh, babylonMesh, byteOffset, dataBuffer);
                 }
                 this.scenes.push(scene);
             }

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


Some files were not shown because too many files changed in this diff