Explorar o código

Merge remote-tracking branch 'origin/master' into user/scramsby/native

Scott Ramsby %!s(int64=7) %!d(string=hai) anos
pai
achega
cfd942b5a6
Modificáronse 100 ficheiros con 18848 adicións e 15084 borrados
  1. 6 0
      .gitignore
  2. 3 0
      .travis.yml
  3. 1 0
      .vscode/settings.json
  4. 1 1
      .vscode/tasks.json
  5. 14958 12507
      Playground/babylon.d.txt
  6. 79 0
      Playground/css/color_ts.css
  7. 422 419
      Playground/debug.html
  8. 0 892
      Playground/examples/list.json
  9. 92 93
      Playground/frame.html
  10. 7 6
      Playground/full.html
  11. 4 3
      Playground/index-local.html
  12. 18 18
      Playground/index.html
  13. 1 1
      Playground/indexStable.html
  14. 346 234
      Playground/js/index.js
  15. 80 0
      Playground/js/libs/typescript.js
  16. 60 0
      Playground/js/ts.js
  17. BIN=BIN
      Playground/scenes/Box/20140615_192225.png
  18. 16 0
      Playground/scenes/Box/Box.mtl
  19. 52 0
      Playground/scenes/Box/Box.obj
  20. BIN=BIN
      Playground/scenes/ufo.glb
  21. 32 0
      Playground/scripts/basic scene.txt
  22. BIN=BIN
      Playground/textures/360photo.jpg
  23. BIN=BIN
      Playground/textures/hollow.png
  24. 492 0
      Playground/ts.html
  25. 0 1
      Playground/zipContent/index.html
  26. 32 25
      Tools/DevLoader/BabylonLoader.js
  27. 290 179
      Tools/Gulp/config.json
  28. 1 1
      Tools/Gulp/gulp-addDtsExport.js
  29. 2 2
      Tools/Gulp/gulp-addES6Exports.js
  30. 1 1
      Tools/Gulp/gulp-addModuleExports.js
  31. 1 1
      Tools/Gulp/gulp-appendSrcToVariable.js
  32. 1 1
      Tools/Gulp/gulp-babylonModule.js
  33. 1 1
      Tools/Gulp/gulp-decorateAndExtends.js
  34. 1 1
      Tools/Gulp/gulp-dtsModuleSupport.js
  35. 1 1
      Tools/Gulp/gulp-es6ModuleExports.js
  36. 42 42
      Tools/Gulp/gulp-removeShaderComments.js
  37. 52 46
      Tools/Gulp/gulp-validateTypedoc.js
  38. 467 240
      Tools/Gulp/gulpfile.js
  39. 29 37
      Tools/Gulp/package.json
  40. 51 19
      Tools/Gulp/processViewerDeclaration.js
  41. 15 5
      Tools/Publisher/index.js
  42. 18 17
      Tools/Publisher/package.json
  43. 139 0
      Tools/WebpackShaderLoader/index.js
  44. BIN=BIN
      Viewer/assets/babylon.woff
  45. 36 22
      Viewer/assets/templates/default/navbar.html
  46. 1 1
      Viewer/assets/templates/default/overlay.html
  47. BIN=BIN
      Viewer/dist/assets/environment/EnvMap_3.0-256.env
  48. BIN=BIN
      Viewer/dist/babylon.woff
  49. 7 0
      Viewer/dist/external/msft/config.json
  50. 25 0
      Viewer/dist/printExample.html
  51. 6 4
      Viewer/package.json
  52. 10 2
      Viewer/src/configuration/configuration.ts
  53. 21 3
      Viewer/src/configuration/configurationCompatibility.ts
  54. 2 1
      Viewer/src/configuration/configurationContainer.ts
  55. 21 0
      Viewer/src/configuration/interfaces/environmentMapConfiguration.ts
  56. 3 1
      Viewer/src/configuration/interfaces/index.ts
  57. 3 1
      Viewer/src/configuration/interfaces/sceneConfiguration.ts
  58. 13 0
      Viewer/src/configuration/interfaces/vrConfiguration.ts
  59. 16 1
      Viewer/src/configuration/loader.ts
  60. 4 0
      Viewer/src/configuration/mappers.ts
  61. 15 6
      Viewer/src/configuration/types/default.ts
  62. 14 14
      Viewer/src/configuration/types/extended.ts
  63. 4 4
      Viewer/src/configuration/types/index.ts
  64. 2 2
      Viewer/src/helper/index.ts
  65. 3 1
      Viewer/src/index.ts
  66. 1 1
      Viewer/src/labs/texture.ts
  67. 25 21
      Viewer/src/loader/modelLoader.ts
  68. 4 4
      Viewer/src/loader/plugins/applyMaterialConfig.ts
  69. 3 3
      Viewer/src/loader/plugins/extendedMaterialLoaderPlugin.ts
  70. 5 4
      Viewer/src/loader/plugins/msftLodLoaderPlugin.ts
  71. 9 2
      Viewer/src/managers/observablesManager.ts
  72. 194 67
      Viewer/src/managers/sceneManager.ts
  73. 4 9
      Viewer/src/managers/telemetryManager.ts
  74. 1 1
      Viewer/src/model/modelAnimation.ts
  75. 14 8
      Viewer/src/model/viewerModel.ts
  76. 4 0
      Viewer/src/optimizer/custom/index.ts
  77. 36 0
      Viewer/src/templating/plugins/hdButtonPlugin.ts
  78. 62 0
      Viewer/src/templating/plugins/printButton.ts
  79. 26 6
      Viewer/src/templating/templateManager.ts
  80. 88 0
      Viewer/src/templating/viewerTemplatePlugin.ts
  81. 149 51
      Viewer/src/viewer/defaultViewer.ts
  82. 175 36
      Viewer/src/viewer/viewer.ts
  83. 3 0
      Viewer/tests/commons/helper.ts
  84. 5 9
      Viewer/tests/unit/src/configuration/updateConfiguration.ts
  85. 14 2
      Viewer/tests/unit/src/viewer/sceneManager.ts
  86. 2 1
      Viewer/tests/unit/tsconfig.json
  87. 4 2
      Viewer/tests/unit/webpack.config.js
  88. BIN=BIN
      Viewer/tests/validation/ReferenceImages/Control.png
  89. BIN=BIN
      Viewer/tests/validation/ReferenceImages/ControlDefault.png
  90. BIN=BIN
      Viewer/tests/validation/ReferenceImages/Diffuse.png
  91. BIN=BIN
      Viewer/tests/validation/ReferenceImages/Emissive.png
  92. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv0-0.png
  93. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv0-100.png
  94. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv0-50.png
  95. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv100-0.png
  96. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv100-100.png
  97. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv100-50.png
  98. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv50-0.png
  99. BIN=BIN
      Viewer/tests/validation/ReferenceImages/MainColorEnv50-100.png
  100. 0 0
      Viewer/tests/validation/ReferenceImages/MainColorEnv50-50.png

+ 6 - 0
.gitignore

@@ -13,6 +13,7 @@ TestResults
 *.user
 *.sln.docstates
 *.map
+!dist/**/*.map
 
 # javascript files
 src/**/*.js
@@ -161,8 +162,12 @@ node_modules
 *.js.fx
 *.d.ts
 !dist/**/*.d.ts
+!dist/**/*.js.map
 !lib.d.ts
 
+# Split declaration file
+!ISplit.d.ts
+
 # local dev
 localDev/src/*
 /dist/preview release/babylon.custom.js
@@ -183,3 +188,4 @@ Viewer/tests/unit/src/**/*.js
 Viewer/tests/Lib/**/*.js
 Viewer/tests/commons/**/*.js
 .sass-cache/
+gui/dist/

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 3 - 0
.travis.yml


+ 1 - 0
.vscode/settings.json

@@ -43,5 +43,6 @@
         "**/*.d.ts": true,
         "assets": true
     },
+    "editor.tabSize": 4,
     "typescript.tsdk": "./Tools/Gulp/node_modules/typescript/lib"
 }

+ 1 - 1
.vscode/tasks.json

@@ -66,7 +66,7 @@
                     "background": {
                         "activeOnStart": true,
                         "beginsPattern": "Project is running at",
-                        "endsPattern": "webpack: Compiled successfully."
+                        "endsPattern": "Compiled successfully."
                     }
                 }
             ],

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 14958 - 12507
Playground/babylon.d.txt


+ 79 - 0
Playground/css/color_ts.css

@@ -0,0 +1,79 @@
+@import url("https://fonts.googleapis.com/css?family=Montserrat:300,400");
+@import url("https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css");
+#waitTitle {
+    color: rgb(208, 23, 211);
+}
+#exampleList #exampleBanner h1 {
+    color: #ae00ef;
+}
+#exampleList .horizontalSeparator {
+    border-top: 1px solid #ae00ef;
+}
+#exampleList .categoryContainer .itemLine .itemContent .itemLineDocLink {
+    color: #ae00ef;
+}
+#exampleList .categoryContainer .itemLine .itemContent .itemLinePGLink {
+    color: #ae00ef;
+}
+
+#fpsLabel {
+    background-color: #9147c9;
+}
+.navbar .title {
+    color: #bb47c9;
+}
+.navbar .version {
+    color: #9147c9;
+}
+
+.button {
+    background-color: #9147c9;
+}
+.button:hover {
+    background-color: #bb47c9;
+}
+.navbar .button.run {
+    background-color: #bb47c9;
+}
+.navbar .select .toDisplay {
+    border: 1px solid #9147c9;
+}
+.navbar .select .subSelect .toDisplaySub {
+    border: 1px solid #9147c9;
+}
+
+.navbar .select .toDisplay .option {
+    font-size: 0.9em;
+    height: 35px;
+    line-height: 35px;
+    padding: 0px 5px 0px 5px;
+    text-align: center;
+    border-bottom : 1px solid rgba(0,0,0,0.1);
+}
+
+.navbar .select .toDisplay .option.light:hover {
+    cursor: pointer;
+    background-color: #d9d9d9;
+}
+
+
+.navbar .select .toDisplay .option.dark {
+    background-color: #333;
+    color: white;
+}
+.navbar .select .toDisplay .option.light {
+    background-color: white;
+    color: #9147c9;
+}
+.navbar .select .toDisplayBig {
+    border: 1px solid #9147c9;
+}
+
+.navbar .select .toDisplayBig.light {    
+    color: #bb47c9;
+}
+.navbar .select .toDisplayBig a.light {
+    color: #9147c9;
+}
+
+

+ 422 - 419
Playground/debug.html

@@ -1,510 +1,513 @@
 <!DOCTYPE html>
 <html>
 
-<head>
-    <title>Babylon.js Playground</title>
-    <meta charset='utf-8' />
-    <meta name="viewport" content="width=device-width, user-scalable=no">
-    <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
-    <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
-    <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
-    <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
-    <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
-    <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
-    <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
-    <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
-    <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
-    <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
-    <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
-    <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
-    <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
-    <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
-    <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
-    <meta name="msapplication-TileColor" content="#ffffff">
-    <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
-    <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
-    <meta name="theme-color" content="#ffffff">
-
-    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <!--For canvas/code separator-->
-    <script src="js/libs/split.js"></script>
-
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
-    <!-- jszip -->
-    <script src="js/libs/jszip.min.js"></script>
-    <script src="js/libs/fileSaver.js"></script>
-    <!-- Monaco -->
-    <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
-    <!-- Babylon.js -->
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.max.js"></script>
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
-    <script src="https://preview.babylonjs.com/gui/babylon.gui.js"></script>
-
-    <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
-
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
-    <link href="css/index.css" rel="stylesheet" />
-
-</head>
-
-<body>
-    <div class="navbar navBar1600">
-        <div class="title">
-            Babylon.js Playground
-        </div>
-        <div class="version" id="mainTitle">
-            v3.0-alpha
-        </div>
-
-        <div class="category">
-            <div class="button run" id="runButton1600">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
+    <head>
+        <title>Babylon.js Playground</title>
+        <meta charset='utf-8' />
+        <meta name="viewport" content="width=device-width, user-scalable=no">
+        <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
+        <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
+        <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
+        <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
+        <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
+        <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
+        <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
+        <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
+        <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
+        <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
+        <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
+        <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
+        <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
+        <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
+        <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
+        <meta name="msapplication-TileColor" content="#ffffff">
+        <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
+        <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
+        <meta name="theme-color" content="#ffffff">
+
+        <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+        <!--For canvas/code separator-->
+        <script src="js/libs/split.js"></script>
+
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
+        <!-- jszip -->
+        <script src="js/libs/jszip.min.js"></script>
+        <script src="js/libs/fileSaver.js"></script>
+
+        <!-- Babylon.js -->
+        <script src="https://preview.babylonjs.com/cannon.js"></script>
+        <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/babylon.max.js"></script>
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.js"></script>
+        <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
+        <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
+        <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
+
+
+
+        <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
+
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
+        <link href="css/index.css" rel="stylesheet" />
+
+        <!-- Monaco -->
+        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
+    </head>
+
+    <body>
+        <div class="navbar navBar1600">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+                v3.0-alpha
+            </div>
+
+            <div class="category">
+                <div class="button run" id="runButton1600">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1600">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1600">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="newButton1600">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1600">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1600">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="zipButton1600">Zip
-                <i class="fa fa-download" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="saveButton1600">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1600">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1600">Dark</div>
-                            <div class="option" id="lightTheme1600">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1600">Dark</div>
+                                <div class="option" id="lightTheme1600">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1600">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1600">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle1600">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1600">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1600">Format code</div>
+                        <div class="option" id="minimapToggle1600">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
                         </div>
-                    </div>
-                    <div class="option" id="safemodeToggle1600">Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option checked" id="editorButton1600">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1600">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1600">Format code</div>
-                    <div class="option" id="minimapToggle1600">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
                     </div>
                 </div>
-            </div>
 
-            <div class="button uncheck" id="debugButton1600">Inspector
-                <i class="fa fa-square-o" aria-hidden="true"></i>
+                <div class="button uncheck" id="debugButton1600">Inspector
+                    <i class="fa fa-square-o" aria-hidden="true"></i>
+                </div>
+                <div class="button" id="metadataButton1600">Metadata</div>
             </div>
-            <div class="button" id="metadataButton1600">Metadata</div>
-        </div>
 
 
 
-        <div class="category right">
-            <div class="button select">
-                <span id="currentVersion1600">Version: Latest</span>
-                <div class="toDisplay">
-                    <div class="option" onclick="setVersion('latest');">Latest</div>
-                    <div class="option" onclick="setVersion('2.5');">2.5</div>
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentVersion1600">Version: Latest</span>
+                    <div class="toDisplay">
+                        <div class="option" onclick="setVersion('latest');">Latest</div>
+                        <div class="option" onclick="setVersion('2.5');">2.5</div>
+                    </div>
+                </div>
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
                 </div>
-            </div>
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
             </div>
         </div>
-    </div>
 
-    <div class="navbar navBar1475">
-        <div class="title">
-            Babylon.js Playground
-        </div>
-        <div class="version" id="mainTitle">
-            v3.0-alpha
-        </div>
+        <div class="navbar navBar1475">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+                v3.0-alpha
+            </div>
 
-        <div class="category">
-            <div class="button run" id="runButton1475">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button run" id="runButton1475">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1475">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1475">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="newButton1475">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1475">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1475">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="zipButton1475">Zip
-                <i class="fa fa-download" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="saveButton1475">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1475">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1475">Dark</div>
-                            <div class="option" id="lightTheme1475">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1475">Dark</div>
+                                <div class="option" id="lightTheme1475">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1475">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1475">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id='safemodeToggle1475'>Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option checked" id="editorButton1475">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1475">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1475">Format code</div>
-                    <div class="option" id="minimapToggle1475">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="debugButton1475">Inspector
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="metadataButton1475">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion1475">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('2.5');">2.5</div>
+                        <div class="option" id='safemodeToggle1475'>Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1475">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1475">Format code</div>
+                        <div class="option" id="minimapToggle1475">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1475">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1475">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1475">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('2.5');">2.5</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
             </div>
         </div>
-    </div>
 
-    <div class="navbar navBar1030">
-        <div class="category">
-            <div class="button run" id="runButton1030">Run
-                <i class="fa fa-play" aria-hidden="true"></i>
+        <div class="navbar navBar1030">
+            <div class="category">
+                <div class="button run" id="runButton1030">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
 
-        <div class="category">
-            <div class="button" id="newButton1030">New
-                <i class="fa fa-file" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="clearButton1030">Clear
-                <i class="fa fa-trash" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="newButton1030">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1030">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button" id="saveButton1030">Save
-                <i class="fa fa-floppy-o" aria-hidden="true"></i>
-            </div>
-            <div class="button removeOnPhone" id="zipButton1030">Zip
-                <i class="fa fa-download" aria-hidden="true"></i>
+            <div class="category">
+                <div class="button" id="saveButton1030">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1030">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme1030">Dark</div>
-                            <div class="option" id="lightTheme1030">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1030">Dark</div>
+                                <div class="option" id="lightTheme1030">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize1030">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1030">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id="safemodeToggle1030">Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option checked" id="editorButton1030">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton1030">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
-                    <div class="option" id="formatButton1030">Format code</div>
-                    <div class="option" id="minimapToggle1030">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="debugButton1030">Inspector
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="metadataButton1030">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion1030">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('2.5');">2.5</div>
+                        <div class="option" id="safemodeToggle1030">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1030">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1030">Format code</div>
+                        <div class="option" id="minimapToggle1030">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1030">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1030">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1030">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('2.5');">2.5</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
             </div>
         </div>
-    </div>
-
-    <div class="navbar navBar750">
-        <div class="category">
-            <div class="button select">File
-                <div class="toDisplay">
-                    <div class="option" id="runButton750">Run
-                        <i class="fa fa-play" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="newButton750">New
-                        <i class="fa fa-file" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="clearButton750">Clear
-                        <i class="fa fa-trash" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="saveButton750">Save
-                        <i class="fa fa-floppy-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="zipButton750">Zip
-                        <i class="fa fa-download" aria-hidden="true"></i>
+
+        <div class="navbar navBar750">
+            <div class="category">
+                <div class="button select">File
+                    <div class="toDisplay">
+                        <div class="option" id="runButton750">Run
+                            <i class="fa fa-play" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="newButton750">New
+                            <i class="fa fa-file" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="clearButton750">Clear
+                            <i class="fa fa-trash" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="saveButton750">Save
+                            <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="zipButton750">Zip
+                            <i class="fa fa-download" aria-hidden="true"></i>
+                        </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category">
-            <div class="button select">Settings
-                <div class="toDisplay">
-                    <div class="option subSelect">Theme
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" id="darkTheme750">Dark</div>
-                            <div class="option" id="lightTheme750">Light</div>
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme750">Dark</div>
+                                <div class="option" id="lightTheme750">Light</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option subSelect">
-                        <span id="currentFontSize750">Font: 14</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setFontSize(12);">12</div>
-                            <div class="option" onclick="setFontSize(14);">14</div>
-                            <div class="option" onclick="setFontSize(16);">16</div>
-                            <div class="option" onclick="setFontSize(18);">18</div>
-                            <div class="option" onclick="setFontSize(20);">20</div>
-                            <div class="option" onclick="setFontSize(22);">22</div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize750">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
                         </div>
-                    </div>
-                    <div class="option" id="safemodeToggle750">Safe mode
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div style="display:none;" class="option checked" id="editorButton750">Editor
-                        <i class="fa fa-check-square" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="fullscreenButton750">Fullscreen</div>
-                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
-                    <div class="option" id="formatButton750">Format code</div>
-                    <div class="option" id="minimapToggle750">Minimap
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="debugButton750">Inspector
-                        <i class="fa fa-square-o" aria-hidden="true"></i>
-                    </div>
-                    <div class="option" id="metadataButton750">Metadata</div>
-                    <div class="option subSelect">
-                        <span id="currentVersion750">Vers. : Latest</span>
-                        <i class="fa fa-chevron-right" aria-hidden="true"></i>
-                        <div class="toDisplaySub">
-                            <div class="option" onclick="setVersion('latest');">Latest</div>
-                            <div class="option" onclick="setVersion('2.5');">2.5</div>
+                        <div class="option" id="safemodeToggle750">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div style="display:none;" class="option checked" id="editorButton750">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton750">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
+                        <div class="option" id="formatButton750">Format code</div>
+                        <div class="option" id="minimapToggle750">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton750">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton750">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion750">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('2.5');">2.5</div>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <div class="category right">
-            <div class="button select">
-                <span class="examplesButton">Examples</span>
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
             </div>
         </div>
-    </div>
 
-    <div class="wrapper">
-        <div id="jsEditor"></div>
-        <div id="canvasZone">
-            <canvas touch-action="none" id="renderCanvas"></canvas>
+        <div class="wrapper">
+            <div id="jsEditor"></div>
+            <div id="canvasZone">
+                <canvas touch-action="none" id="renderCanvas"></canvas>
+            </div>
         </div>
-    </div>
-    <div id="exampleList">
-        <div id="exampleBanner">
-            <h1>Examples</h1>
+        <div id="exampleList">
+            <div id="exampleBanner">
+                <h1>Examples</h1>
+            </div>
+            <div class="horizontalSeparator"></div>
+            <input id="filterBar" type="text" placeholder="Filter examples...">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
-        <div class="horizontalSeparator"></div>
-        <input id="filterBar" type="text" placeholder="Filter examples...">
-        <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
-    </div>
 
-    <span class="label" id="fpsLabel">FPS</span>
+        <span class="label" id="fpsLabel">FPS</span>
 
-    <div id="errorZone">
-    </div>
+        <div id="errorZone">
+        </div>
 
-    <div class="navbarBottom">
-        <div id="statusBar"></div>
-        <div class="links">
-            <div class='link'>
-                <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
-            </div>
-            <div class='link'>
-                <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+        <div class="navbarBottom">
+            <div id="statusBar"></div>
+            <div class="links">
+                <div class='link'>
+                    <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+                </div>
             </div>
         </div>
-    </div>
 
-    <div id="saveLayer" class="save-layer">
-        <div class="save-form">
-            <label for="saveFormTitle">TITLE</label>
-            <div class="separator"></div>
-            <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+        <div id="saveLayer" class="save-layer">
+            <div class="save-form">
+                <label for="saveFormTitle">TITLE</label>
+                <div class="separator"></div>
+                <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
 
-            <label for="saveFormDescription">DESCRIPTION</label>
-            <div class="separator"></div>
-            <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+                <label for="saveFormDescription">DESCRIPTION</label>
+                <div class="separator"></div>
+                <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
 
-            <label for="saveFormTags">TAGS (separated by comma)</label>
-            <div class="separator"></div>
-            <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+                <label for="saveFormTags">TAGS (separated by comma)</label>
+                <div class="separator"></div>
+                <textarea id="saveFormTags" rows="4" cols="10"></textarea>
 
-            <div class="save-form-buttons" id="saveFormButtons">
+                <div class="save-form-buttons" id="saveFormButtons">
 
-                <div id="saveFormButtonOk" class="button">OK</div>
-                <div id="saveFormButtonCancel" class="button">Cancel</div>
+                    <div id="saveFormButtonOk" class="button">OK</div>
+                    <div id="saveFormButtonCancel" class="button">Cancel</div>
+                </div>
             </div>
         </div>
-    </div>
 
-    <script src="https://code.jquery.com/jquery.js"></script>
+        <script src="https://code.jquery.com/jquery.js"></script>
 
-    <script src="js/actions.js"></script>
-    <script src="js/pbt.js"></script>
-    <script src="js/index.js"></script>
+        <script src="js/actions.js"></script>
+        <script src="js/pbt.js"></script>
+        <script src="js/index.js"></script>
 
-    <!-- Global site tag (gtag.js) - Google Analytics -->
-    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
-    <script>
-    window.dataLayer = window.dataLayer || [];
-    function gtag(){dataLayer.push(arguments);}
-    gtag('js', new Date());
+        <!-- Global site tag (gtag.js) - Google Analytics -->
+        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
+        <script>
+            window.dataLayer = window.dataLayer || [];
+            function gtag() { dataLayer.push(arguments); }
+            gtag('js', new Date());
 
-    gtag('config', 'UA-41767310-2');
-    </script>    
-</body>
+            gtag('config', 'UA-41767310-2');
+        </script>
+    </body>
 
 </html>

+ 0 - 892
Playground/examples/list.json

@@ -1,892 +0,0 @@
-{
-    "examples": [
-        {
-            "title": "Animations",
-            "samples": [
-                {
-                    "title": "Bones 101",
-                    "doc": "https://doc.babylonjs.com/How_To/How_to_use_Bones_and_Skeletons",
-                    "icon": "icons/bones.jpg",
-                    "description": "Create complex animations by using skeletons and bones",
-                    "PGID": "#QY1WYT#0"
-                },                
-                {
-                    "title": "Animation blending",
-                    "doc": "https://doc.babylonjs.com/babylon101/Animations#animation-blending",
-                    "icon": "icons/animation_blending.jpg",
-                    "description": "Blend multiple animations together to move from on animation clip to another",
-                    "PGID": "#BCU1XR#0"
-                },
-                {
-                    "title": "Animation weights",
-                    "doc": "https://doc.babylonjs.com/babylon101/animations#animation-weights",
-                    "icon": "icons/animation_weight.jpg",
-                    "description": "Use weights to blend multiple animations together",
-                    "PGID": "#LL5BIQ#0"
-                },                
-                {
-                    "title": "Animation 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/animations",
-                    "icon": "icons/animations.png", 
-                    "description": "How to add animations",
-                    "PGID": "#QYFDDP#1"
-                },
-                {
-                    "title": "Easing functions",
-                    "doc": "https://doc.babylonjs.com/babylon101/animations#easing-functions",
-                    "icon": "icons/easing_functions.png", 
-                    "description": "Create animations with different easing functions",
-                    "PGID": "#8ZNVGR#0"
-                },
-                {
-                    "title": "Instanced bones",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons",
-                    "icon": "icons/instanced_bones.png", 
-                    "description": "Animated skeletons of people walking",
-                    "PGID": "#0K8EYN#0"
-                },
-                {
-                    "title": "Morph targets",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_morphtargets",
-                    "icon": "icons/morph_targets.jpg", 
-                    "description": "Morph a mesh between multiple targets",
-                    "PGID": "#2JDN66#0"
-                }                         
-            ]
-        },
-        {
-            "title": "Cameras",
-            "samples": [
-                {
-                    "title": "Cameras 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/cameras",
-                    "icon": "icons/cameras.png", 
-                    "description": "Types of cameras in babylonjs",
-                    "PGID": "#1A3M5C#0"
-                },
-                {
-                    "title": "Device orientation camera",
-                    "doc": "https://doc.babylonjs.com/babylon101/cameras#device-orientation-camera",
-                    "icon": "icons/deviceOrientationCamera.jpg",
-                    "description": "Camera that reacts to events such as a mobile device being tilted forward or back",
-                    "PGID": "#12WBC#185"
-                }
-            ]
-        },
-        {
-            "title": "GUI",
-            "samples": [
-                {
-                    "title": "GUI",
-                    "doc": "https://doc.babylonjs.com/how_to/gui",
-                    "icon": "icons/gui.png", 
-                    "description": "Babylons graphical user interface provides sliders, buttons, etc.",
-                    "PGID": "#3VMTI9#0"
-                }
-            ]
-        },
-        {
-            "title": "Interactions & events",
-            "samples": [
-                {
-                    "title": "Picking",
-                    "doc": "https://doc.babylonjs.com/babylon101/picking_collisions",
-                    "icon": "icons/picking.png", 
-                    "description": "Use mouse or touch to pick meshes on the screen",
-                    "PGID": "#NU4F6Y#0"
-                },
-                {
-                    "title": "Actions",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_actions",
-                    "icon": "icons/actions.png", 
-                    "description": "Actions are a simple way to add interactions in your scenes",
-                    "PGID": "#J19GYK#0"
-                },
-                {
-                    "title": "Drag and drop",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_actions",
-                    "icon": "icons/drag_and_drop.png", 
-                    "description": "Move meshes around a scene with a mouse",
-                    "PGID": "#UZ23UH#0"
-                },
-                {
-                    "title": "Pointer events handling",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_actions",
-                    "icon": "icons/pointer_events_handling.png", 
-                    "description": "Handle pointer input",
-                    "PGID": "#C245A1#0"
-                }
-            ]
-        },
-        {
-            "title": "Lights",
-            "samples": [
-                {
-                    "title": "Light projected texture",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#projection-texture",
-                    "icon": "icons/projected_texture.jpg",
-                    "description": "Project a texture from a spot light",
-                    "PGID": "#CQNGRK#0"
-                }, 
-                {
-                    "title": "Lights 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights",
-                    "icon": "icons/lights.png", 
-                    "description": "Add lights to a scene",
-                    "PGID": "#AQRDKW#0"
-                }, 
-                {
-                    "title": "Simultaneous lights",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights",
-                    "icon": "icons/sim_lights.jpg", 
-                    "description": "Use multiple lights on a single mesh",
-                    "PGID": "#ZU5TKG#0"
-                },
-                {
-                    "title": "Point light",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-point-light",
-                    "icon": "icons/pointLight.jpg",
-                    "description": "Light emitting from a single point",
-                    "PGID": "#20OAV9#0"
-                },
-                {
-                    "title": "Directional light",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-directional-light",
-                    "icon": "icons/directionalLight.jpg",
-                    "description": "The light is emitted from everywhere in the specified direction, and has an infinite range",
-                    "PGID": "#20OAV9#1"
-                },
-                {
-                    "title": "Spot lgiht",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-spot-light",
-                    "icon": "icons/spotLight.jpg",
-                    "description": "Defines a cone of light pointing in a direction",
-                    "PGID": "#20OAV9#3"
-                },
-                {
-                    "title": "Hemispheric light",
-                    "doc": "https://doc.babylonjs.com/babylon101/lights#the-hemispheric-light",
-                    "icon": "icons/hemLight.jpg",
-                    "description": "Simulate an ambient environment light",
-                    "PGID": "#20OAV9#5"
-                }      
-            ]
-        },
-        {
-            "title": "Loaders",
-            "samples": [
-                {
-                    "title": "Cornell box",
-                    "doc": "https://doc.babylonjs.com/how_to/load_from_any_file_type",
-                    "icon": "icons/cornell.jpg",
-                    "description": "Load a glTF file and setup the environment",
-                    "PGID": "#J5E230#54"
-                },
-                {
-                    "title": "Import meshes",
-                    "doc": "https://doc.babylonjs.com/how_to/load_from_any_file_type",
-                    "icon": "icons/import_meshes.png", 
-                    "description": "Load a mesh from a file and add it to the scene",
-                    "PGID": "#UKNERM#0"
-                },
-                {
-                    "title": "Load glTF model",
-                    "doc": "https://doc.babylonjs.com/how_to/load_from_any_file_type",
-                    "icon": "icons/load_gltf.jpg", 
-                    "description": "Show how to easily load a glTF model",
-                    "PGID": "#PN1NNI#0"
-                },
-                {
-                    "title": "Assets manager",
-                    "doc": "http://localhost:8080/How_To/How_to_use_AssetsManager",
-                    "icon": "icons/assets_manager.jpg", 
-                    "description": "Use AssetsManager to load multiple assets in a centralized way",
-                    "PGID": "#Y7XMAR#0"
-                },
-                {
-                    "title": "Asset container",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_assetcontainer",
-                    "icon": "icons/assetContainer.jpg",
-                    "description": "To add and remove assets from a scene an AssetContainer can be used.",
-                    "PGID": "#17MXFZ#0"
-                }                 
-            ]
-        },         
-        {
-            "title": "Materials",
-            "samples": [   
-                {
-                    "title": "MultiMaterial",
-                    "doc": "https://doc.babylonjs.com/how_to/multi_materials",
-                    "icon": "icons/multi_material.jpg",
-                    "description": "Apply multiple materials to a single mesh using MultiMaterial class",
-                    "PGID": "#2Q4S2S#0"
-                },                   
-                {
-                    "title": "ShaderMaterial",
-                    "doc": "https://doc.babylonjs.com/how_to/shader_material",
-                    "icon": "icons/custom_shader.jpg",
-                    "description": "Use ShaderMaterial to create advanced effects",
-                    "PGID": "#ATDL99#0"
-                },                 
-                {
-                    "title": "X-ray material with Fresnel",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_fresnelparameters",
-                    "icon": "icons/xRayFresnel.jpg",
-                    "description": "Use fresnel parameters to simulate an x-ray effect",
-                    "PGID": "#GK7FK#0"
-                },                         
-                {
-                    "title": "Materials",
-                    "doc": "https://doc.babylonjs.com/babylon101/materials",
-                    "icon": "icons/materials.png", 
-                    "description": "Create and add materials to a mesh",
-                    "PGID": "#DXARSP#0"
-                },
-                {
-                    "title": "PBR",
-                    "doc": "https://doc.babylonjs.com/how_to/physically_based_rendering",
-                    "icon": "icons/pbr.png", 
-                    "description": "Physically based rendering materials",
-                    "PGID": "#8MGKWK#0"
-                },
-                {
-                    "title": "Glossiness and roughness",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.standardmaterial",
-                    "icon": "icons/glossinessAndRoughness.jpg",
-                    "description": "Demonstration of glossiness and rouphness features of standard material",
-                    "PGID": "#RNBKQ#8"
-                },
-                {
-                    "title": "Cell Shading",
-                    "doc": "https://doc.babylonjs.com/extensions/cell",
-                    "icon": "icons/cell_shading.jpg", 
-                    "description": "Cell shading material",
-                    "PGID": "#0ZB1A3#1"
-                },
-                {
-                    "title": "Fur",
-                    "doc": "https://doc.babylonjs.com/extensions/fur",
-                    "icon": "icons/fur.jpg", 
-                    "description": "Fur material",
-                    "PGID": "#VABI8A#0"
-                },
-                {
-                    "title": "Fire",
-                    "doc": "https://doc.babylonjs.com/extensions/Fire",
-                    "icon": "icons/fire.jpg", 
-                    "description": "Fire material",
-                    "PGID": "#LR4YHT#0"
-                },
-                {
-                    "title": "Water",
-                    "doc": "https://doc.babylonjs.com/extensions/water",
-                    "icon": "icons/water.jpg", 
-                    "description": "Water material",
-                    "PGID": "#L76FB1#0"
-                }                      
-            ]
-        },         
-        {
-            "title": "Meshes",
-            "samples": [   
-                {
-                    "title": "Render lines",
-                    "doc": "http://localhost:8080/babylon101/Parametric_Shapes#lines",
-                    "icon": "icons/lines.jpg",
-                    "description": "Use LinesMesh to render lines in 3D",
-                    "PGID": "#SVZL1I#0"
-                },                 
-                {
-                    "title": "Displacement map (CPU)",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.mesh.html#applydisplacementmap",
-                    "icon": "icons/displacement.jpg",
-                    "description": "Update mesh geometry using a displacement map (CPU)",
-                    "PGID": "#04JDPF#0"
-                },                   
-                {
-                    "title": "Constructive solid geometries",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.csg.html",
-                    "icon": "icons/csg.jpg",
-                    "description": "Use boolean operations on meshes using CSG",
-                    "PGID": "#T6NP3F#0"
-                },                  
-                {
-                    "title": "Raycast on height map",
-                    "doc": "https://doc.babylonjs.com/babylon101/raycasts",
-                    "icon": "icons/heightMapRaycast.jpg",
-                    "description": "Raycast to find positions on a heightmap",
-                    "PGID": "#QM57B#0"
-                },                  
-                {
-                    "title": "Basic scene",
-                    "doc": "https://doc.babylonjs.com/features/scene",
-                    "icon": "icons/basic_scene.png", 
-                    "description": "Ball and plane",
-                    "PGID": "#TAZ2CB#0"
-                },
-                {
-                    "title": "Basic elements",
-                    "doc": "https://doc.babylonjs.com/how_to/set_shapes",
-                    "icon": "icons/basic_elements.png", 
-                    "description": "Ball, box, plane, line, etc",
-                    "PGID": "#A1210C#0"
-                },
-                {
-                    "title": "Rotation and scaling",
-                    "doc": "https://doc.babylonjs.com/how_to/rotate",
-                    "icon": "icons/rotation_and_scaling.png", 
-                    "description": "Position mesh layout in space",
-                    "PGID": "#CURCZC#0"
-                },
-                {
-                    "title": "Curved lines",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_path3d",
-                    "icon": "icons/path3D.jpg",
-                    "description": "Use Path3D to create a curved line",
-                    "PGID": "#7SQDY#1"
-                },
-                {
-                    "title": "Rotating mesh to look at a target",
-                    "doc": "https://doc.babylonjs.com/babylon101/position",
-                    "icon": "icons/meshLook.jpg",
-                    "description": "Make a mesh face towards where the pointer hit a plane",
-                    "PGID": "#23M0G6#1"
-                },        
-                {
-                    "title": "Height map",
-                    "doc": "https://doc.babylonjs.com/babylon101/height_map",
-                    "icon": "icons/height_map.png", 
-                    "description": "Use a height map to extrude a plane to create mountains",
-                    "PGID": "#95PXRY#0"
-                },        
-                {
-                    "title": "Extrude polygon",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.meshbuilder#extrudepolygon",
-                    "icon": "icons/extrude_polygon.jpg", 
-                    "description": "Use MeshBuilder to generate geometry from extruded data",
-                    "PGID": "#TFLTJJ#0"
-                },        
-                {
-                    "title": "Polygon mesh",
-                    "doc": "https://doc.babylonjs.com/how_to/polygonmeshbuilder",
-                    "icon": "icons/polygon_mesh.jpg", 
-                    "description": "Use PolygonMeshBuilder to create meshes from polygon data",
-                    "PGID": "#0TQAQU#0"
-                },                     
-                {
-                    "title": "Look at",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.abstractmesh#lookat",
-                    "icon": "icons/look_at.jpg", 
-                    "description": "Use lookAt() function to align meshes on a specific target",
-                    "PGID": "#N2K3ZN#0"
-                },        
-                {
-                    "title": "Ribbons",
-                    "doc": "https://doc.babylonjs.com/how_to/ribbon_tutorial",
-                    "icon": "icons/ribbons.jpg", 
-                    "description": "Use ribbons to create complex meshes",
-                    "PGID": "#29BR2V#1"
-                },        
-                {
-                    "title": "Decals",
-                    "doc": "https://doc.babylonjs.com/how_to/decals",
-                    "icon": "icons/decals.jpg", 
-                    "description": "Create decals to apply additional textures to a portion of a mesh",
-                    "PGID": "#EEUVTY#0"
-                }                                    
-            ]
-        },
-        {
-            "title": "Optimizations",
-            "samples": [
-                {
-                    "title": "Level of detail",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_lod",
-                    "icon": "icons/lod.jpg",
-                    "description": "Use various meshes based on distance to optimize rendering speed",
-                    "PGID": "#7HMHAU#0"
-                },
-                {
-                    "title": "Hardware instancing",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_instances",
-                    "icon": "icons/instances.jpg",
-                    "description": "Use hardware instancing to duplicate meshes at no cost",
-                    "PGID": "#YB006J#0"
-                },
-                {
-                    "title": "Octrees",
-                    "doc": "https://doc.babylonjs.com/how_to/optimizing_your_scene_with_octrees",
-                    "icon": "icons/octree.jpg",
-                    "description": "Use octrees to boost mesh selections when dealing with thousands of objects",
-                    "PGID": "#3YFJ5R#0"
-                }
-            ]
-        },        
-        {
-            "title": "Particles",
-            "samples": [
-                {
-                    "title": "Particles and mirrors",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/particle_mirror.jpg",
-                    "description": "Use particles with a mirror",
-                    "PGID": "#65MUMZ#1"
-                },                  
-                {
-                    "title": "Particles with custom shader",
-                    "doc": "https://doc.babylonjs.com/how_to/customise#custom-effects",
-                    "icon": "icons/custom_particles.jpg",
-                    "description": "Use custom shader to display CPU particles",
-                    "PGID": "#807QEP#0"
-                },                
-                {
-                    "title": "GPU particles",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles#gpu-particles",
-                    "icon": "icons/gpu_particles.jpg",
-                    "description": "Use GPU only to create a massive number of particles",
-                    "PGID": "#PU4WYI#14"
-                },
-                {
-                    "title": "Particles 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/particles.png", 
-                    "description": "Create a particle system and attach it to a moving object",
-                    "PGID": "#EF9X5R#0"
-                },                           
-                {
-                    "title": "Low lying fog",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/lying_fog.jpg",
-                    "description": "Use particle to simulate volumetric fog",
-                    "PGID": "#BHNVUE#1"
-                },                           
-                {
-                    "title": "Particle editor",
-                    "doc": "https://doc.babylonjs.com/babylon101/particles",
-                    "icon": "icons/particle_editor.jpg",
-                    "description": "Online editor to play with particle parameters",
-                    "PGID": "#NNL67B#1"
-                },
-                {
-                    "title": "A lot of triangles with SPS",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/solidParticleSystem.jpg",
-                    "description": "Use solid particle system to create a colorful cube",
-                    "PGID": "#2FPT1A#5"
-                },
-                {
-                    "title": "Solid Particle System facet collision",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/facets.jpg", 
-                    "description": "Use SPS facets to simulate complex mesh collisions",
-                    "PGID": "#6UZDJ9#0"
-                },
-                {
-                    "title": "Solid Particle System collisions",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/sps_collisions.jpg", 
-                    "description": "Use basic geometry to simulate SPS collisions",
-                    "PGID": "#2V1C4Z#0"
-                },
-                {
-                    "title": "Solid Particle System and shadows",
-                    "doc": "https://doc.babylonjs.com/how_to/solid_particle_system",
-                    "icon": "icons/sps_shadows.jpg", 
-                    "description": "Animate SPS with realtime shadows",
-                    "PGID": "#ML2LR9#0"
-                }                        
-            ]
-        },        
-        {
-            "title": "Collisions & intersections",
-            "samples": [
-                {
-                    "title": "Collisions",
-                    "doc": "https://doc.babylonjs.com/babylon101/cameras,_mesh_collisions_and_gravity",
-                    "icon": "icons/collisions.png", 
-                    "description": "Handle basic collisions to avoid a camera going through a box",
-                    "PGID": "#U8MEB0#0"
-                },
-                {
-                    "title": "Intersections",
-                    "doc": "https://doc.babylonjs.com/babylon101/intersect_collisions_-_mesh",
-                    "icon": "icons/intersections.png", 
-                    "description": "Detect when meshes intersect each other",
-                    "PGID": "#KQV9SA#0"
-                }
-            ]
-        },              
-        {
-            "title": "Physics",
-            "samples": [
-                {
-                    "title": "Physics",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_physics_engine",
-                    "icon": "icons/physics.png", 
-                    "description": "How to use physic engines within Babylon",
-                    "PGID": "#7149G4#0"
-                },
-                {
-                    "title": "Cloth",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_physics_engine",
-                    "icon": "icons/cloth.jpg", 
-                    "description": "Use physic engine to simulate cloth",
-                    "PGID": "#7N1BRU#0"
-                }
-            ]
-        },                
-        {
-            "title": "Shadows",
-            "samples": [
-                {
-                    "title": "Contact hardening",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows#contact-hardening-shadow-webgl2-only",
-                    "icon": "icons/pcss.jpg",
-                    "description": "Shadows will get softer when they are further away from the object casting them",
-                    "PGID": "#EYEPRI#3"
-                },
-                {
-                    "title": "Self shadowing #1",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows#exponential-shadow-map",
-                    "icon": "icons/self_shadows1.jpg",
-                    "description": "Use shadow exponential mode to enable self shadowing on a rotating object",
-                    "PGID": "#F4XWU2#0"
-                },                
-                {
-                    "title": "Self shadowing #2",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows#close-exponential-shadow-map",
-                    "icon": "icons/self_shadows2.jpg",
-                    "description": "Use shadow close exponential mode to enable self shadowing on animated object",
-                    "PGID": "#4GAHX6#1"
-                },
-                {
-                    "title": "Shadows 101",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/shadows.png", 
-                    "description": "Setup a scene with lights and meshes to cast different types of shadows",
-                    "PGID": "#IFYDRS#0"
-                },
-                {
-                    "title": "Shadow on transparent textures",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/trasnparent_shadow.jpg",
-                    "description": "Create realistic shadows from a transparent texture",
-                    "PGID": "#2DT16W#2"
-                },
-                {
-                    "title": "Point light shadows",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/point_shadows.jpg", 
-                    "description": "Use point light to cast shadows",
-                    "PGID": "#4MC650#0"
-                },
-                {
-                    "title": "Multi directional lights with soft shadows",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/multi_shadows.jpg", 
-                    "description": "Use multiple directional lights to cast soft shadows",
-                    "PGID": "#KWS7KD#0"
-                },
-                {
-                    "title": "Different shadow filters",
-                    "doc": "https://doc.babylonjs.com/babylon101/shadows",
-                    "icon": "icons/shadow_filters.jpg", 
-                    "description": "Demonstrate different kind of shadows",
-                    "PGID": "#43T193#0"
-                }                                  
-            ]
-        },            
-        {            
-            "title": "Audio",
-            "samples": [
-                {
-                    "title": "Basic sounds",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music",
-                    "icon": "icons/basic_sounds.png", 
-                    "description": "Playing sounds with babylon",
-                    "PGID": "#DXAEUY#0"
-                },
-                {
-                    "title": "Sound on mesh",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music",
-                    "icon": "icons/sound_on_mesh.png", 
-                    "description": "Attach a sound to a mesh which will be modified by the objects position",
-                    "PGID": "#EDVU95#0"
-                },
-                {
-                    "title": "Audio analyzer #1",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music#using-the-analyser",
-                    "icon": "icons/analyzer.jpg", 
-                    "description": "Analyze audio frequencies in realtime",
-                    "PGID": "#TUR5GH#0"
-                },
-                {
-                    "title": "PBR with music analyzer #2",
-                    "doc": "https://doc.babylonjs.com/how_to/playing_sounds_and_music#using-the-analyser",
-                    "icon": "icons/musicAnalyzer.jpg",
-                    "description": "Visualize audio frequencies in realtime",
-                    "PGID": "#2JOSXE#21"
-                }
-            ]
-        },    
-        {
-            "title": "Special FX",
-            "samples": [
-                {
-                    "title": "Fog",
-                    "doc": "https://doc.babylonjs.com/babylon101/Environment#fog",
-                    "icon": "icons/fog.jpg",
-                    "description": "Simulate fog in your scene",
-                    "PGID": "#LR6389#0"
-                },                    
-                {
-                    "title": "Convolution post-process",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.convolutionpostprocess",
-                    "icon": "icons/convolution.jpg",
-                    "description": "Apply emboss filter to the scene using the ConvolutionPostProcess",
-                    "PGID": "#B0RH9H#0"
-                },                  
-                {
-                    "title": "Lens flares",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_lens_flares",
-                    "icon": "icons/lens_flares.jpg",
-                    "description": "Simulate lens flares on the camera",
-                    "PGID": "#ZEB7H6#0"
-                },                 
-                {
-                    "title": "Glass wubble ball",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.abstractmesh#getverticesdata",
-                    "icon": "icons/glassWubbleBall.jpg",
-                    "description": "Warped ball effect",
-                    "PGID": "#CXOLW#3"
-                },                
-                {
-                    "title": "Color curves",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_postprocesses#imageprocessing",
-                    "icon": "icons/color_curves.jpg",
-                    "description": "Apply color curves to your rendering",
-                    "PGID": "#HI65FJ#0"
-                },     
-                {
-                    "title": "Default rendering pipeline",
-                    "doc": "https://doc.babylonjs.com/how_to/using_default_rendering_pipeline",
-                    "icon": "icons/default_pipeline.jpg",
-                    "description": "Bloom, FXAA, sharpen, grain, vignette, chromatic aberration and DoF with one single object",
-                    "PGID": "#Y3C0HQ#146"
-                },                      
-                {
-                    "title": "Depth of field",
-                    "doc": "https://doc.babylonjs.com/how_to/using_default_rendering_pipeline#depth-of-field",
-                    "icon": "icons/dof.jpg",
-                    "description": "Apply depth of field effect",
-                    "PGID": "#8F5HYV#9"
-                },                           
-                {
-                    "title": "Glow layer",
-                    "doc": "https://doc.babylonjs.com/how_to/glow_layer",
-                    "icon": "icons/glow.jpg",
-                    "description": "Generates glow around emissive objects",
-                    "PGID": "#6ZVKE3#0"
-                },
-                {
-                    "title": "Sprites",
-                    "doc": "https://doc.babylonjs.com/babylon101/sprites",
-                    "icon": "icons/sprites.png", 
-                    "description": "Load and display sprites",
-                    "PGID": "#9RI8CG#0"
-                },
-                {
-                    "title": "Environment",
-                    "doc": "https://doc.babylonjs.com/babylon101/environment",
-                    "icon": "icons/environment.png", 
-                    "description": "Adding a skybox and fog",
-                    "PGID": "#7G0IQW#0"
-                },
-                {
-                    "title": "Fresnel",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_fresnelparameters",
-                    "icon": "icons/fresnel.png", 
-                    "description": "Renders spheres to simulate a fresnel lens",
-                    "PGID": "#AQZJ4C#0"
-                },
-                {
-                    "title": "SSAO rendering pipeline",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_ssao_rendering_pipeline",
-                    "icon": "icons/ssao_1.png", 
-                    "description": "Screen space ambient occlusion",
-                    "PGID": "#N96NXC#0"
-                },
-                {
-                    "title": "SSAO rendering pipeline (WebGL2)",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.ssao2renderingpipeline",
-                    "icon": "icons/ssao_2.png", 
-                    "description": "Screen space ambient occlusion with WebGL2",
-                    "PGID": "#7D2QDD#0"
-                },
-                {
-                    "title": "Volumetric Light Scattering",
-                    "doc": "https://doc.babylonjs.com/how_to/using_the_volumetric_lightscattering_post-process",
-                    "icon": "icons/volumetric_light_scattering.png", 
-                    "description": "Simulates light scattering due to light hitting the atmosphere",
-                    "PGID": "#V2DAKC#0"
-                },
-                {
-                    "title": "Refraction and Reflection",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_fresnelparameters",
-                    "icon": "icons/refraction_and_reflection.png", 
-                    "description": "Simulate how light would reflect and refract with a sphere",
-                    "PGID": "#XH85A9#0"
-                },
-                {
-                    "title": "Portals",
-                    "doc": "https://doc.babylonjs.com/resources/shaderintro",
-                    "icon": "icons/portals.jpg",
-                    "description": "Portal effect created using custom shaders",
-                    "PGID": "#EEOWP#7"
-                },
-                {
-                    "title": "Warp speed !",
-                    "doc": "https://doc.babylonjs.com/how_to/shader_material",
-                    "icon": "icons/warpSpeed.jpg",
-                    "description": "Fly though stars using a custom shader texture",
-                    "PGID": "#1WBBW0#1"
-                },
-                {
-                    "title": "Hypnotizing infinite loader",
-                    "doc": "https://doc.babylonjs.com/babylon101/position",
-                    "icon": "icons/infiniteLoader.jpg",
-                    "description": "Visually apealing loading animation",
-                    "PGID": "#VUJG1#1"
-                },            
-                {
-                    "title": "Realtime refraction",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_reflection_probes",
-                    "icon": "icons/refraction.jpg", 
-                    "description": "use reflection probes to simulate realtime refraction",
-                    "PGID": "#RRYXWN#0"
-                },
-                {
-                    "title": "Realtime reflection",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_reflection_probes",
-                    "icon": "icons/reflection.jpg", 
-                    "description": "use reflection probes to simulate realtime reflection",
-                    "PGID": "#SF5RCN#0"
-                },                
-                {
-                    "title": "Motion blur",
-                    "doc": "https://doc.babylonjs.com/how_to/using_standard_rendering_pipeline#setting-up-the-motion-blur",
-                    "icon": "icons/motion_blur.jpg", 
-                    "description": "Use the standard rendering pipeline to simulate motion blur",
-                    "PGID": "#ZMAJZB#0"
-                },
-                {
-                    "title": "Highlight layer",
-                    "doc": "https://doc.babylonjs.com/how_to/highlight_layer",
-                    "icon": "icons/highlights.jpg", 
-                    "description": "Highlight a mesh",
-                    "PGID": "#7EESGZ#0"
-                },
-                {
-                    "title": "Lens effects",
-                    "doc": "https://doc.babylonjs.com/how_to/using_depth-of-field_and_other_lens_effects",
-                    "icon": "icons/lens_effect.jpg", 
-                    "description": "Create photographic effect with the LensRenderingPipeline",
-                    "PGID": "#B7JHWD#0"
-                }                           
-            ]
-        },
-        {
-            "title": "Textures",
-            "samples": [   
-                {
-                    "title": "Saving dynamic texture on disk",
-                    "doc": "https://doc.babylonjs.com/how_to/dynamictexture",
-                    "icon": "icons/savingDynamicTexture.jpg",
-                    "description": "Save a texture generated at runtime using DynamicTexture",
-                    "PGID": "#CA4SM#1"
-                },                
-                {
-                    "title": "360 videos",
-                    "doc": "https://doc.babylonjs.com/how_to/360videodome",
-                    "icon": "icons/360.jpg",
-                    "description": "Easily display and control 360 videos",
-                    "PGID": "#1E9JQ8#7"
-                },                
-                {
-                    "title": "ProceduralTexture",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_procedural_textures",
-                    "icon": "icons/procedural_texture.png", 
-                    "description": "Use procedual textures for wood, grass, marble, fire, etc.",
-                    "PGID": "#B2ZXG6#0"
-                },
-                {
-                    "title": "Local cubemaps",
-                    "doc": "https://doc.babylonjs.com/how_to/reflect#cubetexture",
-                    "icon": "icons/local_cubemap.jpg",
-                    "description": "Improve cubemaps with local mode",
-                    "PGID": "#RNASML#4"
-                },                 
-                {
-                    "title": "Starfield procedural texture",
-                    "doc": "https://doc.babylonjs.com/how_to/how_to_use_procedural_textures",
-                    "icon": "icons/starfield.jpg", 
-                    "description": "Use the starfield procedual texture to simulate space",
-                    "PGID": "#ZQWE4G#0"
-                },
-                {
-                    "title": "Equirectangular map as reflection texture",
-                    "doc": "https://doc.babylonjs.com/how_to/reflect",
-                    "icon": "icons/equMapOnReflectionTexture.jpg",
-                    "description": "Using Equirectangular maps as a reflection texture",
-                    "PGID": "#23IQHK#2"
-                },
-                {
-                    "title": "Mirrors",
-                    "doc": "https://doc.babylonjs.com/how_to/reflect",
-                    "icon": "icons/mirrors.jpg",
-                    "description": "Shows how to use mirrors in babylon",
-                    "PGID": "#2EP7UB#0"
-                },
-                {
-                    "title": "Custom render targets",
-                    "doc": "https://doc.babylonjs.com/api/classes/babylon.rendertargettexture",
-                    "icon": "icons/custom_rendertarget.jpg",
-                    "description": "Use render target textures to generate procedural data",
-                    "PGID": "#CJWDJR#0"
-                },
-                {
-                    "title": "Bump texture",
-                    "doc": "https://doc.babylonjs.com/how_to/more_materials#bump-map",
-                    "icon": "icons/bump.jpg",
-                    "description": "Use normal map to simulate bump",
-                    "PGID": "#RK0W5S#0"
-                }                              
-            ]
-        },
-        {
-            "title": "VR",
-            "samples": [
-                {
-                    "title": "WebVR",
-                    "doc": "https://doc.babylonjs.com/how_to/webvr_helper",
-                    "icon": "icons/webvr.png", 
-                    "description": "View a basic mesh and interact with a gui in WebVR",
-                    "PGID": "#TAFSN0#2"
-                } 
-            ]
-        },
-        {
-            "title": "Misc.",
-            "samples": [
-                {
-                    "title": "Charting",
-                    "doc": "https://doc.babylonjs.com/babylon101/",
-                    "icon": "icons/charting.jpg", 
-                    "description": "Creates a 3D charting presentation",
-                    "PGID": "#8PY6X5#1"
-                } 
-            ]
-        }         
-    ]
-}

+ 92 - 93
Playground/frame.html

@@ -1,98 +1,97 @@
 <!DOCTYPE html>
 <html>
 
-<head>
-    <title>Babylon.js Playground</title>
-    <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
-    <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
-    <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
-    <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
-    <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
-    <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
-    <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
-    <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
-    <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
-    <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
-    <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
-    <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
-    <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
-    <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
-    <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
-    <meta name="msapplication-TileColor" content="#ffffff">
-    <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
-    <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
-    <meta name="theme-color" content="#ffffff">
-    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
-
-    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
-    <!-- Babylon.js -->
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/earcut.min.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.js"></script>
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
-    <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
-
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
-    <link href="frame.css" rel="stylesheet" />
-</head>
-
-<body>
-    <canvas touch-action="none" id="renderCanvas" tabindex="1"></canvas>
-
-    <span class="label" id="fpsLabel">FPS</span>
-
-    <a class="link" id="refresh" href="#">Reload</a>
-    <a class="link" id="link" href="#" target="_blank">Edit</a>
-
-    <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="js/frame.js"></script>
-
-    <!-- Global site tag (gtag.js) - Google Analytics -->
-    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
-    <script>
-    window.dataLayer = window.dataLayer || [];
-    function gtag(){dataLayer.push(arguments);}
-    gtag('js', new Date());
-
-    gtag('config', 'UA-41767310-2');
-    </script>    
-</body>
+    <head>
+        <title>Babylon.js Playground</title>
+        <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
+        <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
+        <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
+        <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
+        <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
+        <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
+        <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
+        <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
+        <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
+        <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
+        <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
+        <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
+        <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
+        <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
+        <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
+        <meta name="msapplication-TileColor" content="#ffffff">
+        <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
+        <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
+        <meta name="theme-color" content="#ffffff">
+        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
+
+        <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+
+        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
+        <!-- Babylon.js -->
+        <script src="https://preview.babylonjs.com/cannon.js"></script>
+        <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/earcut.min.js"></script>
+        <script src="https://preview.babylonjs.com/babylon.js"></script>
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+        <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
+
+        <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
+        <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
+        <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
+
+        <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
+
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
+        <link href="frame.css" rel="stylesheet" />
+    </head>
+
+    <body>
+        <canvas touch-action="none" id="renderCanvas" tabindex="1"></canvas>
+
+        <span class="label" id="fpsLabel">FPS</span>
+
+        <a class="link" id="refresh" href="#">Reload</a>
+        <a class="link" id="link" href="#" target="_blank">Edit</a>
+
+        <script src="https://code.jquery.com/jquery.js"></script>
+        <script src="js/frame.js"></script>
+
+        <!-- Global site tag (gtag.js) - Google Analytics -->
+        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
+        <script>
+            window.dataLayer = window.dataLayer || [];
+            function gtag() { dataLayer.push(arguments); }
+            gtag('js', new Date());
+
+            gtag('config', 'UA-41767310-2');
+        </script>
+    </body>
 
 </html>

+ 7 - 6
Playground/full.html

@@ -29,6 +29,7 @@
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/babylon.js"></script>
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
 
         <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
@@ -39,7 +40,7 @@
 
         <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
 
-        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+
 
         <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
         <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
@@ -54,12 +55,12 @@
         <!-- Global site tag (gtag.js) - Google Analytics -->
         <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
         <script>
-        window.dataLayer = window.dataLayer || [];
-        function gtag(){dataLayer.push(arguments);}
-        gtag('js', new Date());
+            window.dataLayer = window.dataLayer || [];
+            function gtag() { dataLayer.push(arguments); }
+            gtag('js', new Date());
 
-        gtag('config', 'UA-41767310-2');
-        </script>        
+            gtag('config', 'UA-41767310-2');
+        </script>
     </body>
 
 </html>

+ 4 - 3
Playground/index-local.html

@@ -18,7 +18,7 @@
         <script src="../dist/preview%20release/Oimo.js"></script>
         <script src="../dist/preview%20release/earcut.min.js"></script>
         <!-- Monaco -->
-        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
         <!-- Babylon.js -->
         <script src="../tools/DevLoader/BabylonLoader.js"></script>
 
@@ -381,7 +381,7 @@
             </div>
             <div class="horizontalSeparator"></div>
             <input id="filterBar" type="text" placeholder="Filter examples...">
-            <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
 
         <span class="label" id="fpsLabel">FPS</span>
@@ -447,6 +447,7 @@
         <script src="js/pbt.js"></script>
         <script>
             BABYLONDEVTOOLS.Loader
+                .require('node_modules/monaco-editor/min/vs/loader.js')
                 .require('js/index.js')
                 .load(function () {
                     BABYLON.DracoCompression.Configuration.decoder = {
@@ -458,4 +459,4 @@
         </script>
     </body>
 
-</html>
+</html>

+ 18 - 18
Playground/index.html

@@ -37,26 +37,26 @@
         <script src="https://preview.babylonjs.com/cannon.js"></script>
         <script src="https://preview.babylonjs.com/Oimo.js"></script>
         <script src="https://preview.babylonjs.com/earcut.min.js"></script>
-        <!-- Monaco -->
-        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
         <!-- Babylon.js -->
         <script src="https://preview.babylonjs.com/babylon.js"></script>
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
         <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
         <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
-
         <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
-
         <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
-
         <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
-
         <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
 
-        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+        <!-- Monaco -->
+        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
+
+        <!-- Extensions -->
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js" async></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js" async></script>
+        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.navmesh.js"></script>
+        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.js"></script>
 
-        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>
-        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
         <link href="css/index.css" rel="stylesheet" />
     </head>
 
@@ -410,13 +410,13 @@
                 <canvas touch-action="none" id="renderCanvas"></canvas>
             </div>
         </div>
-        <div id="exampleList">
+        <div id="exampleList" class="javascript">
             <div id="exampleBanner">
                 <h1>Examples</h1>
             </div>
             <div class="horizontalSeparator"></div>
             <input id="filterBar" type="text" placeholder="Filter examples...">
-            <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
 
         <span class="label" id="fpsLabel">FPS</span>
@@ -481,16 +481,16 @@
         <script src="js/actions.js"></script>
         <script src="js/pbt.js"></script>
         <script src="js/index.js"></script>
-        
+
         <!-- Global site tag (gtag.js) - Google Analytics -->
         <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
         <script>
-        window.dataLayer = window.dataLayer || [];
-        function gtag(){dataLayer.push(arguments);}
-        gtag('js', new Date());
+            window.dataLayer = window.dataLayer || [];
+            function gtag() { dataLayer.push(arguments); }
+            gtag('js', new Date());
 
-        gtag('config', 'UA-41767310-2');
-        </script>        
+            gtag('config', 'UA-41767310-2');
+        </script>
     </body>
 
 </html>

+ 1 - 1
Playground/indexStable.html

@@ -407,7 +407,7 @@
             </div>
             <div class="horizontalSeparator"></div>
             <input id="filterBar" type="text" placeholder="Filter examples...">
-            <img id="filterBarClear" src="http://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
         </div>
 
         <span class="label" id="fpsLabel">FPS</span>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 346 - 234
Playground/js/index.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 80 - 0
Playground/js/libs/typescript.js


+ 60 - 0
Playground/js/ts.js

@@ -0,0 +1,60 @@
+
+var compilerTriggerTimeoutID;
+function triggerCompile(d, func) {
+    if (compilerTriggerTimeoutID !== null) {
+        window.clearTimeout(compilerTriggerTimeoutID);
+    }
+    compilerTriggerTimeoutID = window.setTimeout(function () {
+        try {
+             
+            var output = transpileModule(d, {
+                module: ts.ModuleKind.AMD,
+                target: ts.ScriptTarget.ES5,
+                noLib: true,
+                noResolve: true,
+                suppressOutputPathCheck: true
+            });
+            if (typeof output === "string") {
+                func(output);
+            }
+        }
+        catch (e) {
+            showError(e.message, e);
+        }
+    }, 100);
+}
+function transpileModule(input, options) {
+    var inputFileName = options.jsx ? "module.tsx" : "module.ts";
+    var sourceFile = ts.createSourceFile(inputFileName, input, options.target || ts.ScriptTarget.ES5);
+    // Output
+    var outputText;
+    var program = ts.createProgram([inputFileName], options, {
+        getSourceFile: function (fileName) { return fileName.indexOf("module") === 0 ? sourceFile : undefined; },
+        writeFile: function (_name, text) { outputText = text; },
+        getDefaultLibFileName: function () { return "lib.d.ts"; },
+        useCaseSensitiveFileNames: function () { return false; },
+        getCanonicalFileName: function (fileName) { return fileName; },
+        getCurrentDirectory: function () { return ""; },
+        getNewLine: function () { return "\r\n"; },
+        fileExists: function (fileName) { return fileName === inputFileName; },
+        readFile: function () { return ""; },
+        directoryExists: function () { return true; },
+        getDirectories: function () { return []; }
+    });
+    // Emit
+    program.emit();
+    if (outputText === undefined) {
+        throw new Error("Output generation failed");
+    }
+    return outputText;
+}
+
+function getRunCode(jsEditor, callBack) {
+    triggerCompile(jsEditor.getValue(), function(result) {
+        callBack(result + "var createScene = function() { return Playground.CreateScene(engine, engine.getRenderingCanvas()); }")
+    });
+}
+
+var defaultScene = "scripts/basic scene.txt";
+var monacoMode = "typescript";
+

BIN=BIN
Playground/scenes/Box/20140615_192225.png


+ 16 - 0
Playground/scenes/Box/Box.mtl

@@ -0,0 +1,16 @@
+# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
+# File Created: 29.06.2018 00:36:27
+
+newmtl 01___Default
+	Ns 10.0000
+	Ni 1.5000
+	d 1.0000
+	Tr 0.0000
+	Tf 1.0000 1.0000 1.0000 
+	illum 2
+	Ka 0.5882 0.5882 0.5882
+	Kd 0.5882 0.5882 0.5882
+	Ks 0.0000 0.0000 0.0000
+	Ke 0.0000 0.0000 0.0000
+	map_Ka 20140615_192225.png
+	map_Kd 20140615_192225.png

+ 52 - 0
Playground/scenes/Box/Box.obj

@@ -0,0 +1,52 @@
+# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
+# File Created: 29.06.2018 00:36:27
+
+mtllib Box.mtl
+
+#
+# object Box001
+#
+
+v  -13.8390 0.0000 16.0985
+v  -13.8390 0.0000 -16.1733
+v  13.2327 0.0000 -16.1733
+v  13.2327 0.0000 16.0985
+v  -13.8390 23.5656 16.0985
+v  13.2327 23.5656 16.0985
+v  13.2327 23.5656 -16.1733
+v  -13.8390 23.5656 -16.1733
+# 8 vertices
+
+vn -0.5774 -0.5774 0.5774
+vn -0.5774 -0.5774 -0.5774
+vn 0.5774 -0.5774 -0.5774
+vn 0.5774 -0.5774 0.5774
+vn -0.5774 0.5774 0.5774
+vn 0.5774 0.5774 0.5774
+vn 0.5774 0.5774 -0.5774
+vn -0.5774 0.5774 -0.5774
+# 8 vertex normals
+
+vt 1.0000 0.0000 0.0000
+vt 1.0000 1.0000 0.0000
+vt 0.0000 1.0000 0.0000
+vt 0.0000 0.0000 0.0000
+# 4 texture coords
+
+o Box001
+g Box001
+usemtl 01___Default
+s 2
+f 1/1/1 2/2/2 3/3/3 4/4/4 
+s 4
+f 5/4/5 6/1/6 7/2/7 8/3/8 
+s 8
+f 1/4/1 4/1/4 6/2/6 5/3/5 
+s 16
+f 4/4/4 3/1/3 7/2/7 6/3/6 
+s 32
+f 3/4/3 2/1/2 8/2/8 7/3/7 
+s 64
+f 2/4/2 1/1/1 5/2/5 8/3/8 
+# 6 polygons
+

BIN=BIN
Playground/scenes/ufo.glb


+ 32 - 0
Playground/scripts/basic scene.txt

@@ -0,0 +1,32 @@
+class Playground { 
+    public static CreateScene(engine: BABYLON.Engine, canvas: HTMLCanvasElement): BABYLON.Scene {
+        // This creates a basic Babylon Scene object (non-mesh)
+        var scene = new BABYLON.Scene(engine);
+
+        // This creates and positions a free camera (non-mesh)
+        var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
+
+        // This targets the camera to scene origin
+        camera.setTarget(BABYLON.Vector3.Zero());
+
+        // This attaches the camera to the canvas
+        camera.attachControl(canvas, true);
+
+        // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
+        var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
+
+        // Default intensity is 1. Let's dim the light a small amount
+        light.intensity = 0.7;
+
+        // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
+        var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
+
+        // Move the sphere upward 1/2 its height
+        sphere.position.y = 1;
+
+        // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
+        var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);
+
+        return scene;
+    }
+}

BIN=BIN
Playground/textures/360photo.jpg


BIN=BIN
Playground/textures/hollow.png


+ 492 - 0
Playground/ts.html

@@ -0,0 +1,492 @@
+<!DOCTYPE html>
+<html>
+
+    <head>
+        <title>Babylon.js Playground</title>
+        <meta charset='utf-8' />
+        <meta name="viewport" content="width=device-width, user-scalable=no">
+        <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
+        <link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
+        <link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
+        <link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
+        <link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
+        <link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
+        <link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
+        <link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
+        <link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
+        <link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
+        <link rel="icon" type="image/png" sizes="192x192" href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
+        <link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
+        <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
+        <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
+        <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
+        <meta name="msapplication-TileColor" content="#ffffff">
+        <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
+        <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
+        <meta name="theme-color" content="#ffffff">
+
+        <script src="js/libs/pep.min.js"></script>
+        <!--For canvas/code separator-->
+        <script src="js/libs/split.js"></script>
+
+        <script src="js/libs/dat.gui.min.js"></script>
+        <!-- jszip -->
+        <script src="js/libs/jszip.min.js"></script>
+        <script src="js/libs/fileSaver.js"></script>
+        <!-- Dependencies -->
+        <script src="https://preview.babylonjs.com/cannon.js"></script>
+        <script src="https://preview.babylonjs.com/Oimo.js"></script>
+        <script src="https://preview.babylonjs.com/earcut.min.js"></script>
+        <!-- Babylon.js -->
+        <script src="https://preview.babylonjs.com/babylon.js"></script>
+        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
+        <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
+        <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
+        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
+        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
+        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
+        <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
+
+        <!-- Monaco -->
+        <script src="node_modules/monaco-editor/min/vs/loader.js"></script>
+
+        <!-- Extensions -->
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js" async></script>
+        <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js" async></script>
+        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.navmesh.js"></script>
+        <script src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.js"></script>
+                               
+        <link href="css/index.css" rel="stylesheet" />
+        <link href="css/color_ts.css" rel="stylesheet" />
+    </head>
+
+    <body>
+        <div class="navbar navBar1600">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+            </div>
+
+            <div class="category">
+                <div class="button run" id="runButton1600">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
+
+
+            <div class="category">
+                <div class="button" id="newButton1600">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1600">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button" id="saveButton1600">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1600">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1600">Dark</div>
+                                <div class="option" id="lightTheme1600">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1600">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle1600">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1600">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1600">Format code</div>
+                        <div class="option" id="minimapToggle1600">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="button uncheck" id="debugButton1600">Inspector
+                    <i class="fa fa-square-o" aria-hidden="true"></i>
+                </div>
+                <div class="button" id="metadataButton1600">Metadata</div>
+            </div>
+
+
+
+            <div class="category right">
+                <div class="button select">
+                    <span id="currentVersion1600">Version: Latest</span>
+                    <div class="toDisplay">
+                        <div class="option" onclick="setVersion('latest');">Latest</div>
+                        <div class="option" onclick="setVersion('stable');">Stable</div>
+                    </div>
+                </div>
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
+            </div>
+        </div>
+
+        <div class="navbar navBar1475">
+            <div class="title">
+                Babylon.js Playground
+            </div>
+            <div class="version" id="mainTitle">
+            </div>
+
+            <div class="category">
+                <div class="button run" id="runButton1475">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
+
+
+            <div class="category">
+                <div class="button" id="newButton1475">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1475">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button" id="saveButton1475">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1475">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1475">Dark</div>
+                                <div class="option" id="lightTheme1475">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1475">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id='safemodeToggle1475'>Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1475">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1475">Format code</div>
+                        <div class="option" id="minimapToggle1475">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1475">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1475">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1475">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
+            </div>
+        </div>
+
+        <div class="navbar navBar1030">
+            <div class="category">
+                <div class="button run" id="runButton1030">Run
+                    <i class="fa fa-play" aria-hidden="true"></i>
+                </div>
+            </div>
+
+
+            <div class="category">
+                <div class="button" id="newButton1030">New
+                    <i class="fa fa-file" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="clearButton1030">Clear
+                    <i class="fa fa-trash" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button" id="saveButton1030">Save
+                    <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                </div>
+                <div class="button removeOnPhone" id="zipButton1030">Zip
+                    <i class="fa fa-download" aria-hidden="true"></i>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme1030">Dark</div>
+                                <div class="option" id="lightTheme1030">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize1030">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle1030">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option checked" id="editorButton1030">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
+                        <div class="option" id="formatButton1030">Format code</div>
+                        <div class="option" id="minimapToggle1030">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton1030">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton1030">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion1030">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="category right">
+                <div class="button select">
+                    <span class="examplesButton">Examples</span>
+                </div>
+            </div>
+        </div>
+
+        <div class="navbar navBar750">
+            <div class="category">
+                <div class="button select">File
+                    <div class="toDisplay">
+                        <div class="option" id="runButton750">Run
+                            <i class="fa fa-play" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="newButton750">New
+                            <i class="fa fa-file" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="clearButton750">Clear
+                            <i class="fa fa-trash" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="saveButton750">Save
+                            <i class="fa fa-floppy-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="zipButton750">Zip
+                            <i class="fa fa-download" aria-hidden="true"></i>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+            <div class="category">
+                <div class="button select">Settings
+                    <div class="toDisplay">
+                        <div class="option subSelect">Theme
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" id="darkTheme750">Dark</div>
+                                <div class="option" id="lightTheme750">Light</div>
+                            </div>
+                        </div>
+                        <div class="option subSelect">
+                            <span id="currentFontSize750">Font: 14</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setFontSize(12);">12</div>
+                                <div class="option" onclick="setFontSize(14);">14</div>
+                                <div class="option" onclick="setFontSize(16);">16</div>
+                                <div class="option" onclick="setFontSize(18);">18</div>
+                                <div class="option" onclick="setFontSize(20);">20</div>
+                                <div class="option" onclick="setFontSize(22);">22</div>
+                            </div>
+                        </div>
+                        <div class="option" id="safemodeToggle750">Safe mode
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div style="display:none;" class="option checked" id="editorButton750">Editor
+                            <i class="fa fa-check-square" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="fullscreenButton750">Fullscreen</div>
+                        <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
+                        <div class="option" id="formatButton750">Format code</div>
+                        <div class="option" id="minimapToggle750">Minimap
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="debugButton750">Inspector
+                            <i class="fa fa-square-o" aria-hidden="true"></i>
+                        </div>
+                        <div class="option" id="metadataButton750">Metadata</div>
+                        <div class="option subSelect">
+                            <span id="currentVersion750">Vers. : Latest</span>
+                            <i class="fa fa-chevron-right" aria-hidden="true"></i>
+                            <div class="toDisplaySub">
+                                <div class="option" onclick="setVersion('latest');">Latest</div>
+                                <div class="option" onclick="setVersion('stable');">Stable</div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="wrapper">
+            <div id="jsEditor"></div>
+            <div id="canvasZone">
+                <canvas touch-action="none" id="renderCanvas"></canvas>
+            </div>
+        </div>
+        <div id="exampleList" class = "typescript">
+            <div id="exampleBanner">
+                <h1>Examples</h1>
+            </div>
+            <div class="horizontalSeparator"></div>
+            <input id="filterBar" type="text" placeholder="Filter examples...">
+            <img id="filterBarClear" src="https://d33wubrfki0l68.cloudfront.net/17ca450bae302631f4857cd8c3992234ec5dd9a7/057f9/img/ui/clear_button.png">
+        </div>
+
+        <span class="label" id="fpsLabel">FPS</span>
+
+        <div id="errorZone">
+        </div>
+
+        <div class="navbarBottom">
+            <div id="statusBar"></div>
+            <div class="links">
+                <div class='link'>
+                    <a target='_new' href="https://www.netlify.com/">Deployed by Netlify</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="http://www.html5gamedevs.com/forum/16-babylonjs/">Forum</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://www.babylonjs.com/sandbox">Sandbox</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com">Documentation</a>
+                </div>
+                <div class='link'>
+                    <a target='_new' href="https://doc.babylonjs.com/playground">Search</a>
+                </div>
+            </div>
+        </div>
+
+        <div id="saveLayer" class="save-layer">
+            <div class="save-form">
+                <label for="saveFormTitle">TITLE</label>
+                <div class="separator"></div>
+                <input type="text" maxlength="120" id="saveFormTitle" class="save-form-title">
+
+                <label for="saveFormDescription">DESCRIPTION</label>
+                <div class="separator"></div>
+                <textarea id="saveFormDescription" rows="4" cols="10"></textarea>
+
+                <label for="saveFormTags">TAGS (separated by comma)</label>
+                <div class="separator"></div>
+                <textarea id="saveFormTags" rows="4" cols="10"></textarea>
+
+                <div class="save-form-buttons" id="saveFormButtons">
+
+                    <div id="saveFormButtonOk" class="button">OK</div>
+                    <div id="saveFormButtonCancel" class="button">Cancel</div>
+                </div>
+            </div>
+        </div>
+
+        <div id="waitDiv">
+            <span id="waitTitle">Babylon.js Playground
+                <BR>
+                <BR>
+                <BR>
+            </span>
+            <img src="waitlogo.png" id="waitLogo" />
+        </div>
+
+        <script src="js/libs/jquery.min.js"></script>
+
+        <script src="js/actions.js"></script>
+        <script src="js/pbt.js"></script>
+        <script src="js/libs/typescript.js"></script>
+        <script src="js/index.js"></script>
+        <script src="js/ts.js"></script>
+        
+        <!-- Global site tag (gtag.js) - Google Analytics -->
+        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-41767310-2"></script>
+        <script>
+        window.dataLayer = window.dataLayer || [];
+        function gtag(){dataLayer.push(arguments);}
+        gtag('js', new Date());
+
+        gtag('config', 'UA-41767310-2');
+        </script>        
+    </body>
+
+</html>

+ 0 - 1
Playground/zipContent/index.html

@@ -40,7 +40,6 @@
     <canvas id="renderCanvas"></canvas>
     <script>
         var canvas = document.getElementById("renderCanvas");
-        var engine = new BABYLON.Engine(canvas, true);
 
 ####INJECT####
 

+ 32 - 25
Tools/DevLoader/BabylonLoader.js

@@ -130,7 +130,7 @@ var BABYLONDEVTOOLS;
             var style = document.createElement('link');
             style.href = url;
             style.rel = "stylesheet";
-            style.type = "text/css"
+            style.type = "text/css";
             document.head.appendChild(style);
         }
 
@@ -141,36 +141,44 @@ var BABYLONDEVTOOLS;
         }
 
         Loader.prototype.loadLibrary = function (library, module) {
+            if (library.preventLoadLibrary) {
+                return;
+            }
+
             if (!useDist) {
-                var i = 0;
-                for (; i < library.files.length; i++) {
-                    var file = library.files[i];
-                    if (file.indexOf('lib.d.ts') > 0) {
-                        continue;
-                    }
+                if (library.useOutputForDebugging) {
+                    this.loadScript(babylonJSPath + '/.temp' + module.build.distOutputDirectory + library.output);
+                } else {
+                    var i = 0;
+                    for (; i < library.files.length; i++) {
+                        var file = library.files[i];
+                        if (file.indexOf('lib.d.ts') > 0) {
+                            continue;
+                        }
 
-                    file = file.replace('.ts', '.js');
-                    file = file.replace('../', '');
-                    file = babylonJSPath + '/' + file;
-                    this.loadScript(file);
-                }
+                        file = file.replace('.ts', '.js');
+                        file = file.replace('../', '');
+                        file = babylonJSPath + '/' + file;
+                        this.loadScript(file);
+                    }
 
-                if (library.shaderFiles && library.shaderFiles.length > 0) {
-                    var shaderFile = library.shaderFiles[0];
-                    var endDirectoryIndex = shaderFile.lastIndexOf('/');
-                    shaderFile = shaderFile.substring(0, endDirectoryIndex + 1);
-                    shaderFile += library.output.replace('.js', '.js.fx');
-                    this.loadScript(shaderFile);
-                    if (library.shadersIncludeFiles) {
-                        var includeShaderFile = shaderFile.replace('.js.fx', '.js.include.fx');
-                        this.loadScript(includeShaderFile);
+                    if (library.shaderFiles && library.shaderFiles.length > 0) {
+                        var shaderFile = library.shaderFiles[0];
+                        var endDirectoryIndex = shaderFile.lastIndexOf('/');
+                        shaderFile = shaderFile.substring(0, endDirectoryIndex + 1);
+                        shaderFile += library.output.replace('.js', '.js.fx');
+                        this.loadScript(shaderFile);
+                        if (library.shadersIncludeFiles) {
+                            var includeShaderFile = shaderFile.replace('.js.fx', '.js.include.fx');
+                            this.loadScript(includeShaderFile);
+                        }
                     }
                 }
             }
             else if (min) {
                 if (library.webpack) {
                     if (module.build.distOutputDirectory)
-                        this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output.replace('.js', '.bundle.js'));
+                        this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output);
                 }
                 else {
                     this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output.replace('.js', '.min.js'));
@@ -181,6 +189,7 @@ var BABYLONDEVTOOLS;
                     this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output);
             }
 
+            // Currently not being used
             if (!min && library.sassFiles && library.sassFiles.length > 0) {
                 var cssFile = library.output.replace('.js', '.css');
                 cssFile = babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + cssFile;
@@ -242,10 +251,8 @@ var BABYLONDEVTOOLS;
 
             // Modules
             if (loadModules) {
+
                 for (var i = 0; i < settings.modules.length; i++) {
-                    if (settings.modules[i] === "viewer") {
-                        continue;
-                    }
                     this.loadModule(settings[settings.modules[i]]);
                 }
             }

+ 290 - 179
Tools/Gulp/config.json

@@ -8,13 +8,14 @@
         "declarationModuleFilename": "babylon.module.d.ts",
         "outputDirectory": "../../dist/preview release",
         "playgroundDirectory": "../../Playground/",
+        "tempDirectory": "../../.temp/",
         "intellisenseFile": "babylon.d.txt",
         "intellisenseSources": [
             "../../dist/preview release/babylon.d.ts",
             "../../dist/preview release/gui/babylon.gui.d.ts",
             "../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts",
             "../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts",
-            "../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
         ],
         "outputCustomConfigurationsDirectory": "../../dist/preview release/customConfigurations",
         "srcOutputDirectory": "../../src/",
@@ -99,6 +100,8 @@
             "gizmos",
             "morphTargets",
             "octrees",
+            "anaglyph",
+            "stereoscopic",
             "vr",
             "virtualJoystick",
             "optimizations",
@@ -117,16 +120,25 @@
             "environmentHelper",
             "particleHelper",
             "videoDome",
-            "photoDome"
+            "photoDome",
+            "behaviors",
+            "imageProcessing",
+            "occlusionQuery",
+            "transformFeedback",
+            "noise",
+            "videoRecorder"
         ],
         "minimal": [
+            "meshBuilder",
             "freeCamera",
             "hemisphericLight"
         ],
-        "minimalWithBuilder": [
+        "360Viewer": [
+            "arcRotateCamera",
             "meshBuilder",
-            "freeCamera",
-            "hemisphericLight"
+            "picking",
+            "backgroundMaterial",
+            "videoDome"
         ]
     },
     "workloads": {
@@ -161,10 +173,13 @@
                 "../../src/Cameras/babylon.camera.js",
                 "../../src/Rendering/babylon.renderingManager.js",
                 "../../src/Rendering/babylon.renderingGroup.js",
+                "../../src/babylon.sceneComponent.js",
+                "../../src/babylon.abstractScene.js",
                 "../../src/babylon.scene.js",
                 "../../src/babylon.assetContainer.js",
                 "../../src/Mesh/babylon.buffer.js",
                 "../../src/Mesh/babylon.vertexBuffer.js",
+                "../../src/Materials/Textures/babylon.internalTextureLoader.js",
                 "../../src/Materials/Textures/babylon.internalTextureTracker.js",
                 "../../src/Materials/Textures/babylon.internalTexture.js",
                 "../../src/Materials/Textures/babylon.baseTexture.js",
@@ -175,12 +190,7 @@
                 "../../src/Materials/babylon.uniformBuffer.js",
                 "../../src/Mesh/babylon.mesh.vertexData.js",
                 "../../src/Mesh/babylon.geometry.js",
-                "../../src/PostProcess/babylon.postProcessManager.js",
                 "../../src/Tools/babylon.performanceMonitor.js",
-                "../../src/Materials/babylon.imageProcessingConfiguration.js",
-                "../../src/Materials/Textures/babylon.colorGradingTexture.js",
-                "../../src/Materials/babylon.colorCurves.js",
-                "../../src/Behaviors/babylon.behavior.js",
                 "../../src/Materials/babylon.materialHelper.js",
                 "../../src/Materials/babylon.pushMaterial.js",
                 "../../src/Materials/babylon.standardMaterial.js"
@@ -231,14 +241,65 @@
                 "fogFragment"
             ]
         },
+        "transformFeedback": {
+            "files": [
+                "../../src/Engine/Extensions/babylon.engine.transformFeedback.js"
+            ],
+            "dependUpon": [
+                "core",
+                "debug"
+            ]
+        },
+        "occlusionQuery": {
+            "files": [
+                "../../src/Engine/Extensions/babylon.engine.occlusionQuery.js"
+            ],
+            "dependUpon": [
+                "core",
+                "debug"
+            ]
+        },
+        "behaviors": {
+            "files": [
+                "../../src/Behaviors/babylon.behavior.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },
+        "imageProcessing": {
+            "files": [
+                "../../src/Materials/babylon.imageProcessingConfiguration.js",
+                "../../src/Materials/Textures/babylon.colorGradingTexture.js",
+                "../../src/Materials/babylon.colorCurves.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },
+        "noise": {
+            "files": [
+                "../../src/Materials/Textures/Procedurals/babylon.noiseProceduralTexture.js"
+            ],
+            "dependUpon": [
+                "core",
+                "procedural"
+            ],
+            "shaders": [
+                "noise.fragment"
+            ]
+        },
         "particles": {
             "files": [
                 "../../src/Particles/babylon.particle.js",
+                "../../src/Particles/babylon.baseParticleSystem.js",
                 "../../src/Particles/babylon.particleSystem.js",
-                "../../src/Particles/EmitterTypes/babylon.IParticleEmitterType.js",
                 "../../src/Particles/EmitterTypes/babylon.boxParticleEmitter.js",
                 "../../src/Particles/EmitterTypes/babylon.coneParticleEmitter.js",
-                "../../src/Particles/EmitterTypes/babylon.sphereParticleEmitter.js"
+                "../../src/Particles/EmitterTypes/babylon.sphereParticleEmitter.js",
+                "../../src/Particles/EmitterTypes/babylon.hemisphericParticleEmitter.js",
+                "../../src/Particles/EmitterTypes/babylon.pointParticleEmitter.js",
+                "../../src/Particles/babylon.particleSystemComponent.js"
             ],
             "dependUpon": [
                 "core"
@@ -254,7 +315,8 @@
             ],
             "dependUpon": [
                 "core",
-                "particles"
+                "particles",
+                "transformFeedback"
             ],
             "shaders": [
                 "gpuRenderParticles.vertex",
@@ -301,15 +363,18 @@
                 "../../src/Behaviors/Cameras/babylon.autoRotationBehavior.js"
             ],
             "dependUpon": [
-                "core"
+                "behaviors"
             ]
         },
         "meshBehaviors": {
             "files": [
-                "../../src/Behaviors/Mesh/babylon.pointerDragBehavior.js"
+                "../../src/Behaviors/Mesh/babylon.pointerDragBehavior.js",
+                "../../src/Behaviors/Mesh/babylon.multiPointerScaleBehavior.js",
+                "../../src/Behaviors/Mesh/babylon.sixDofDragBehavior.js",
+                "../../src/Behaviors/Mesh/babylon.attachToBoxBehavior.js"
             ],
             "dependUpon": [
-                "core"
+                "behaviors"
             ]
         },
         "textureTools": {
@@ -432,7 +497,8 @@
                 "../../src/Materials/PBR/babylon.pbrSpecularGlossinessMaterial.js"
             ],
             "dependUpon": [
-                "core"
+                "core",
+                "harmonics"
             ],
             "shaders": [
                 "pbr.vertex",
@@ -521,7 +587,8 @@
                 "../../src/Audio/babylon.audioEngine.js",
                 "../../src/Audio/babylon.sound.js",
                 "../../src/Audio/babylon.soundtrack.js",
-                "../../src/Audio/babylon.analyser.js"
+                "../../src/Audio/babylon.analyser.js",
+                "../../src/Audio/babylon.weightedsound.js"
             ],
             "dependUpon": [
                 "core"
@@ -530,6 +597,7 @@
         "additionalTextures": {
             "files": [
                 "../../src/Materials/Textures/babylon.cubeTexture.js",
+                "../../src/Materials/Textures/babylon.rawCubeTexture.js",
                 "../../src/Materials/Textures/babylon.renderTargetTexture.js",
                 "../../src/Materials/Textures/babylon.multiRenderTarget.js",
                 "../../src/Materials/Textures/babylon.mirrorTexture.js",
@@ -643,7 +711,8 @@
                 "../../src/Gamepad/Controllers/babylon.genericController.js",
                 "../../src/Gamepad/Controllers/babylon.windowsMotionController.js",
                 "../../src/Gamepad/Controllers/babylon.gearVRController.js",
-                "../../src/Gamepad/Controllers/babylon.daydreamController.js"
+                "../../src/Gamepad/Controllers/babylon.daydreamController.js",
+                "../../src/Gamepad/babylon.gamepadSceneComponent.js"
             ],
             "dependUpon": [
                 "core"
@@ -691,6 +760,7 @@
         },
         "postProcesses": {
             "files": [
+                "../../src/PostProcess/babylon.postProcessManager.js",
                 "../../src/PostProcess/babylon.postProcess.js",
                 "../../src/PostProcess/babylon.passPostProcess.js"
             ],
@@ -864,7 +934,8 @@
                 "../../src/PostProcess/babylon.imageProcessingPostProcess.js"
             ],
             "dependUpon": [
-                "postProcesses"
+                "postProcesses",
+                "imageProcessing"
             ],
             "shaders": [
                 "imageProcessing.fragment"
@@ -890,7 +961,8 @@
                 "../../src/PostProcess/babylon.imageProcessingPostProcess.js"
             ],
             "dependUpon": [
-                "postProcesses"
+                "postProcesses",
+                "imageProcessing"
             ],
             "shaders": [
                 "refraction.fragment",
@@ -965,15 +1037,13 @@
         },
         "hdr": {
             "files": [
-                "../../src/Math/babylon.sphericalPolynomial.js",
-                "../../src/Tools/HDR/babylon.cubemapToSphericalPolynomial.js",
-                "../../src/Tools/HDR/babylon.panoramaToCubemap.js",
                 "../../src/Tools/HDR/babylon.hdr.js",
-                "../../src/Tools/babylon.environmentTextureTools.js",
-                "../../src/Materials/Textures/babylon.hdrCubeTexture.js"
+                "../../src/Materials/Textures/babylon.hdrCubeTexture.js",
+                "../../src/Tools/HDR/babylon.panoramaToCubemap.js"
             ],
             "dependUpon": [
-                "core"
+                "core",
+                "harmonics"
             ]
         },
         "csg": {
@@ -995,6 +1065,7 @@
         "lensFlares": {
             "files": [
                 "../../src/LensFlare/babylon.lensFlare.js",
+                "../../src/LensFlare/babylon.lensFlareSystemSceneComponent.js",
                 "../../src/LensFlare/babylon.lensFlareSystem.js"
             ],
             "dependUpon": [
@@ -1019,16 +1090,61 @@
                 "picking"
             ]
         },
+        "harmonics": {
+            "files": [
+                "../../src/Math/babylon.sphericalPolynomial.js",
+                "../../src/Tools/HDR/babylon.cubemapToSphericalPolynomial.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },
         "textureFormats": {
+            "files": [],
+            "dependUpon": [
+                "dds",
+                "tga",
+                "ktx",
+                "env"
+            ]
+        },
+        "dds": {
             "files": [
-                "../../src/Tools/babylon.tga.js",
                 "../../src/Tools/babylon.dds.js",
-                "../../src/Tools/babylon.khronosTextureContainer.js"
+                "../../src/Materials/Textures/Loaders/babylon.ddsTextureLoader.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },
+        "tga": {
+            "files": [
+                "../../src/Tools/babylon.tga.js",
+                "../../src/Materials/Textures/Loaders/babylon.tgaTextureLoader.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
+        },
+        "ktx": {
+            "files": [
+                "../../src/Tools/babylon.khronosTextureContainer.js",
+                "../../src/Materials/Textures/Loaders/babylon.ktxTextureLoader.js"
             ],
             "dependUpon": [
                 "core"
             ]
         },
+        "env": {
+            "files": [
+                "../../src/Tools/babylon.environmentTextureTools.js",
+                "../../src/Materials/Textures/Loaders/babylon.envTextureLoader.js"
+            ],
+            "dependUpon": [
+                "core",
+                "harmonics"
+            ]
+        },
         "debug": {
             "files": [
                 "../../src/Debug/babylon.skeletonViewer.js",
@@ -1065,6 +1181,7 @@
                 "../../src/Gizmos/babylon.positionGizmo.js",
                 "../../src/Gizmos/babylon.rotationGizmo.js",
                 "../../src/Gizmos/babylon.scaleGizmo.js",
+                "../../src/Gizmos/babylon.boundingBoxGizmo.js",
                 "../../src/Gizmos/babylon.gizmoManager.js"
             ],
             "dependUpon": [
@@ -1091,28 +1208,62 @@
                 "core"
             ]
         },
-        "vr": {
+        "anaglyph": {
             "files": [
-                "../../src/PostProcess/babylon.vrDistortionCorrectionPostProcess.js",
                 "../../src/PostProcess/babylon.anaglyphPostProcess.js",
+                "../../src/Cameras/Stereoscopic/babylon.anaglyphArcRotateCamera.js",
+                "../../src/Cameras/Stereoscopic/babylon.anaglyphFreeCamera.js",
+                "../../src/Cameras/Stereoscopic/babylon.anaglyphGamepadCamera.js",
+                "../../src/Cameras/Stereoscopic/babylon.anaglyphUniversalCamera.js"
+            ],
+            "dependUpon": [
+                "core",
+                "postProcesses",
+                "freeCamera",
+                "gamepad"
+            ],
+            "shaders": [
+                "anaglyph.fragment"
+            ]
+        },
+        "stereoscopic": {
+            "files": [
                 "../../src/PostProcess/babylon.stereoscopicInterlacePostProcess.js",
+                "../../src/Cameras/Stereoscopic/babylon.stereoscopicArcRotateCamera.js",
+                "../../src/Cameras/Stereoscopic/babylon.stereoscopicFreeCamera.js",
+                "../../src/Cameras/Stereoscopic/babylon.stereoscopicGamepadCamera.js",
+                "../../src/Cameras/Stereoscopic/babylon.stereoscopicUniversalCamera.js"
+            ],
+            "dependUpon": [
+                "core",
+                "postProcesses",
+                "freeCamera",
+                "gamepad"
+            ],
+            "shaders": [
+                "stereoscopicInterlace.fragment"
+            ]
+        },
+        "vr": {
+            "files": [
+                "../../src/PostProcess/babylon.vrDistortionCorrectionPostProcess.js",
                 "../../src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.js",
                 "../../src/Cameras/Inputs/babylon.arcRotateCameraVRDeviceOrientationInput.js",
                 "../../src/Cameras/VR/babylon.vrCameraMetrics.js",
                 "../../src/Cameras/VR/babylon.webVRCamera.js",
                 "../../src/Cameras/babylon.deviceOrientationCamera.js",
-                "../../src/Cameras/VR/babylon.vrDeviceOrientationCamera.js",
-                "../../src/Cameras/babylon.stereoscopicCameras.js",
+                "../../src/Cameras/VR/babylon.vrDeviceOrientationFreeCamera.js",
+                "../../src/Cameras/VR/babylon.vrDeviceOrientationArcRotateCamera.js",
+                "../../src/Cameras/VR/babylon.vrDeviceOrientationGamepadCamera.js",
                 "../../src/Cameras/VR/babylon.vrExperienceHelper.js"
             ],
             "dependUpon": [
                 "core",
                 "postProcesses",
-                "freeCamera"
+                "freeCamera",
+                "gamepad"
             ],
             "shaders": [
-                "anaglyph.fragment",
-                "stereoscopicInterlace.fragment",
                 "vrDistortionCorrection.fragment"
             ]
         },
@@ -1140,6 +1291,7 @@
             "files": [
                 "../../src/Rendering/babylon.outlineRenderer.js",
                 "../../src/Rendering/babylon.edgesRenderer.js",
+                "../../src/Layer/babylon.effectLayerSceneComponent.js",
                 "../../src/Layer/babylon.effectLayer.js",
                 "../../src/Layer/babylon.highlightLayer.js",
                 "../../src/Layer/babylon.glowLayer.js"
@@ -1185,6 +1337,7 @@
         },
         "layer": {
             "files": [
+                "../../src/Layer/babylon.layerSceneComponent.js",
                 "../../src/Layer/babylon.layer.js"
             ],
             "dependUpon": [
@@ -1224,7 +1377,8 @@
         },
         "particleHelper": {
             "files": [
-                "../../src/Helpers/babylon.particleHelper.js"
+                "../../src/Particles/babylon.particleSystemSet.js",
+                "../../src/Particles/babylon.particleHelper.js"
             ],
             "dependUpon": [
                 "particles"
@@ -1249,7 +1403,16 @@
                 "meshBuilder",
                 "additionalTextures"
             ]
+        },
+        "videoRecorder": {
+            "files": [
+                "../../src/Tools/babylon.videoRecorder.js"
+            ],
+            "dependUpon": [
+                "core"
+            ]
         }
+
     },
     "typescript": [
         "../../src/**/*.ts",
@@ -1272,8 +1435,8 @@
         "proceduralTexturesLibrary",
         "loaders",
         "serializers",
-        "inspector",
         "gui",
+        "inspector",
         "viewer",
         "viewer-assets"
     ],
@@ -1612,6 +1775,7 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts",
@@ -1619,7 +1783,8 @@
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_lights.ts",
-                    "../../loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts"
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/EXT_lights_imageBased.ts"
                 ],
                 "doNotIncludeInBundle": true,
                 "output": "babylon.glTF2FileLoader.js"
@@ -1636,6 +1801,7 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts",
@@ -1643,7 +1809,8 @@
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_lights.ts",
-                    "../../loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts"
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/EXT_lights_imageBased.ts"
                 ],
                 "output": "babylon.glTFFileLoader.js"
             }
@@ -1678,13 +1845,10 @@
                     "../../serializers/src/glTF/2.0/babylon.glTFSerializer.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFExporter.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFData.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFMaterial.ts",
+                    "../../serializers/src/glTF/2.0/babylon.glTFMaterialExporter.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFAnimation.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFUtilities.ts"
                 ],
-                "shaderFiles": [
-                    "../../serializers/src/glTF/2.0/shaders/setAlphaToOne.fragment.fx"
-                ],
                 "output": "babylon.glTF2Serializer.js"
             }
         ],
@@ -1708,141 +1872,72 @@
     "gui": {
         "libraries": [
             {
-                "files": [
-                    "../../gui/src/2D/style.ts",
-                    "../../gui/src/2D/valueAndUnit.ts",
-                    "../../gui/src/2D/advancedDynamicTexture.ts",
-                    "../../gui/src/2D/measure.ts",
-                    "../../gui/src/2D/math2D.ts",
-                    "../../gui/src/2D/multiLinePoint.ts",
-                    "../../gui/src/2D/controls/control.ts",
-                    "../../gui/src/2D/controls/container.ts",
-                    "../../gui/src/2D/controls/stackPanel.ts",
-                    "../../gui/src/2D/controls/rectangle.ts",
-                    "../../gui/src/2D/controls/ellipse.ts",
-                    "../../gui/src/2D/controls/line.ts",
-                    "../../gui/src/2D/controls/slider.ts",
-                    "../../gui/src/2D/controls/checkbox.ts",
-                    "../../gui/src/2D/controls/radioButton.ts",
-                    "../../gui/src/2D/controls/textBlock.ts",
-                    "../../gui/src/2D/controls/image.ts",
-                    "../../gui/src/2D/controls/button.ts",
-                    "../../gui/src/2D/controls/colorpicker.ts",
-                    "../../gui/src/2D/controls/inputText.ts",
-                    "../../gui/src/2D/controls/virtualKeyboard.ts",
-                    "../../gui/src/2D/controls/multiLine.ts",
-                    "../../gui/src/2D/controls/grid.ts",                    
-                    "../../gui/src/3D/gui3DManager.ts",
-                    "../../gui/src/3D/materials/fluentMaterial.ts",
-                    "../../gui/src/3D/vector3WithInfo.ts",
-                    "../../gui/src/3D/controls/control3D.ts",
-                    "../../gui/src/3D/controls/container3D.ts",
-                    "../../gui/src/3D/controls/abstractButton3D.ts",
-                    "../../gui/src/3D/controls/button3D.ts",
-                    "../../gui/src/3D/controls/holographicButton.ts",
-                    "../../gui/src/3D/controls/stackPanel3D.ts",
-                    "../../gui/src/3D/controls/volumeBasedPanel.ts",
-                    "../../gui/src/3D/controls/spherePanel.ts"
-                ],
-                "shaderFiles": [
-                    "../../gui/src/3D/materials/shaders/fluent.vertex.fx",
-                    "../../gui/src/3D/materials/shaders/fluent.fragment.fx"
-                ],
-                "output": "babylon.gui.js",
-                "buildAsModule": true,
-                "moduleName": "babylonjs-gui",
-                "moduleDeclaration": {
-                    "name": "GUI",
-                    "module": "babylonjs-gui"
-                }
+                "files": [],
+                "noBundleInName": true,
+                "output": "babylon.gui.min.js",
+                "webpack": "../../gui/webpack.config.js",
+                "bundle": "true",
+                "babylonIncluded": false,
+                "useOutputForDebugging": true
             }
         ],
         "build": {
-            "srcOutputDirectory": "../../gui/",
-            "distOutputDirectory": "/gui/"
+            "srcOutputDirectory": "../../gui/src/",
+            "distOutputDirectory": "/gui/",
+            "dtsBundle": {
+                "name": "babylonjs-gui",
+                "main": "../../dist/preview release/gui/build/index.d.ts",
+                "out": "../babylon.gui.module.d.ts",
+                "baseDir": "../../dist/preview release/gui/build/",
+                "headerText": "BabylonJS GUI"
+            },
+            "processDeclaration": {
+                "filename": "babylon.gui.module.d.ts",
+                "packageName": "babylonjs-gui",
+                "moduleName": "BABYLON.GUI",
+                "importsToRemove": [],
+                "classMap": {
+                    "babylonjs": "BABYLON",
+                    "babylonjs-loaders": "BABYLON",
+                    "babylonjs-serializers": "BABYLON"
+                }
+            }
         }
     },
     "inspector": {
         "libraries": [
             {
-                "files": [
-                    "../../inspector/src/Inspector.ts",
-                    "../../inspector/src/properties.ts",
-                    "../../inspector/src/properties_gui.ts",
-                    "../../inspector/src/gui/BasicElement.ts",
-                    "../../inspector/src/adapters/Adapter.ts",
-                    "../../inspector/src/adapters/CameraAdapter.ts",
-                    "../../inspector/src/adapters/PhysicsImpostorAdapter.ts",
-                    "../../inspector/src/adapters/GUIAdapter.ts",
-                    "../../inspector/src/adapters/SoundAdapter.ts",
-                    "../../inspector/src/adapters/TextureAdapter.ts",
-                    "../../inspector/src/adapters/LightAdapter.ts",
-                    "../../inspector/src/adapters/MaterialAdapter.ts",
-                    "../../inspector/src/adapters/MeshAdapter.ts",
-                    "../../inspector/src/adapters/PhysicsImpostorAdapter.ts",
-                    "../../inspector/src/details/DetailPanel.ts",
-                    "../../inspector/src/details/Property.ts",
-                    "../../inspector/src/details/PropertyLine.ts",
-                    "../../inspector/src/gui/ColorElement.ts",
-                    "../../inspector/src/gui/ColorPickerElement.ts",
-                    "../../inspector/src/gui/CubeTextureElement.ts",
-                    "../../inspector/src/gui/HDRCubeTextureElement.ts",
-                    "../../inspector/src/gui/SearchBar.ts",
-                    "../../inspector/src/gui/TextureElement.ts",
-                    "../../inspector/src/gui/Tooltip.ts",
-                    "../../inspector/src/helpers/Helpers.ts",
-                    "../../inspector/src/scheduler/Scheduler.ts",
-                    "../../inspector/src/tabs/Tab.ts",
-                    "../../inspector/src/tabs/PropertyTab.ts",
-                    "../../inspector/src/tabs/CameraTab.ts",
-                    "../../inspector/src/tabs/GUITab.ts",
-                    "../../inspector/src/tabs/PhysicsTab.ts",
-                    "../../inspector/src/tabs/SoundTab.ts",
-                    "../../inspector/src/tabs/TextureTab.ts",
-                    "../../inspector/src/tabs/LightTab.ts",
-                    "../../inspector/src/tabs/MaterialTab.ts",
-                    "../../inspector/src/tabs/MeshTab.ts",
-                    "../../inspector/src/tabs/SceneTab.ts",
-                    "../../inspector/src/tabs/ConsoleTab.ts",
-                    "../../inspector/src/tabs/StatsTab.ts",
-                    "../../inspector/src/tabs/GLTFTab.ts",
-                    "../../inspector/src/tabs/ToolsTab.ts",
-                    "../../inspector/src/tabs/TabBar.ts",
-                    "../../inspector/src/tools/AbstractTool.ts",
-                    "../../inspector/src/tools/PauseScheduleTool.ts",
-                    "../../inspector/src/tools/PickTool.ts",
-                    "../../inspector/src/tools/PopupTool.ts",
-                    "../../inspector/src/tools/RefreshTool.ts",
-                    "../../inspector/src/tools/LabelTool.ts",
-                    "../../inspector/src/tools/Toolbar.ts",
-                    "../../inspector/src/tools/DisposeTool.ts",
-                    "../../inspector/src/tools/FullscreenTool.ts",
-                    "../../inspector/src/tree/TreeItem.ts",
-                    "../../inspector/src/treetools/AbstractTreeTool.ts",
-                    "../../inspector/src/treetools/BoundingBox.ts",
-                    "../../inspector/src/treetools/CameraPOV.ts",
-                    "../../inspector/src/treetools/SoundInteractions.ts",
-                    "../../inspector/src/treetools/Checkbox.ts",
-                    "../../inspector/src/treetools/DebugArea.ts",
-                    "../../inspector/src/treetools/Info.ts",
-                    "../../inspector/src/lib.d.ts"
-                ],
-                "sassFiles": [
-                    "../../inspector/sass/**/*.scss"
-                ],
-                "output": "babylon.inspector.js",
+                "files": [],
+                "sassFiles": [],
+                "output": "babylon.inspector.bundle.js",
                 "webpack": "../../inspector/webpack.config.js",
                 "bundle": "true",
-                "moduleDeclaration": {
-                    "name": "INSPECTOR",
-                    "module": "babylonjs-inspector"
-                },
-                "extendsRoot": true
+                "extendsRoot": true,
+                "useOutputForDebugging": true
             }
         ],
         "build": {
-            "srcOutputDirectory": "../../inspector/",
-            "distOutputDirectory": "/inspector/"
+            "srcOutputDirectory": "../../inspector/src/",
+            "distOutputDirectory": "/inspector/",
+            "dtsBundle": {
+                "name": "babylonjs-inspector",
+                "main": "../../dist/preview release/inspector/build/index.d.ts",
+                "out": "../babylon.inspector.module.d.ts",
+                "baseDir": "../../dist/preview release/inspector/build/",
+                "headerText": "BabylonJS Inspector"
+            },
+            "processDeclaration": {
+                "filename": "babylon.inspector.module.d.ts",
+                "packageName": "babylonjs-inspector",
+                "moduleName": "INSPECTOR",
+                "importsToRemove": [],
+                "classMap": {
+                    "babylonjs": "BABYLON",
+                    "babylonjs-loaders": "BABYLON",
+                    "babylonjs-serializers": "BABYLON",
+                    "babylonjs-gui": "BABYLON.GUI"
+                }
+            }
         }
     },
     "viewer": {
@@ -1857,21 +1952,35 @@
                     "name": "BabylonViewer",
                     "module": "babylonjs-viewer"
                 },
-                "babylonIncluded": true
+                "babylonIncluded": true,
+                "noWatch": true,
+                "preventLoadLibrary": true
             }
         ],
         "build": {
             "srcOutputDirectory": "../../Viewer/",
+            "distOutputDirectory": "/viewer/",
             "dtsBundle": {
                 "name": "babylonjs-viewer",
-                "main": "../../Viewer/dist/build/src/index.d.ts",
-                "out": "../../../../dist/preview release/viewer/babylon.viewer.module.d.ts",
-                "legacyDeclaration": true,
+                "main": "../../dist/preview release/viewer/build/src/index.d.ts",
+                "out": "../../babylon.viewer.module.d.ts",
                 "prependText": "/// <reference path=\"./babylon.d.ts\"/>\n/// <reference path=\"./babylon.glTF2Interface.d.ts\"/>\n/// <reference path=\"./babylonjs.loaders.d.ts\"/>\ndeclare module \"babylonjs-loaders\"{ export=BABYLON;}\n"
             },
+            "processDeclaration": {
+                "packageName": "babylonjs-viewer",
+                "moduleName": "BabylonViewer",
+                "importsToRemove": [
+                    "pep",
+                    "babylonjs-loaders"
+                ],
+                "classMap": {
+                    "babylonjs": "BABYLON",
+                    "babylonjs-loaders": "BABYLON"
+                }
+            },
             "outputs": [
                 {
-                    "destination": [
+                    "destinations": [
                         {
                             "filename": "viewer.js",
                             "outputDirectory": "/../../Viewer/dist/"
@@ -1882,14 +1991,14 @@
                             "addBabylonDeclaration": [
                                 "babylon.d.ts",
                                 "loaders/babylonjs.loaders.d.ts",
-                                "gltf2Interface/babylon.glTF2Interface.d.ts"
+                                "glTF2Interface/babylon.glTF2Interface.d.ts"
                             ]
                         }
                     ],
                     "minified": true
                 },
                 {
-                    "destination": [
+                    "destinations": [
                         {
                             "filename": "viewer.max.js",
                             "outputDirectory": "/../../Viewer/dist/"
@@ -1915,23 +2024,25 @@
                     "name": "BabylonViewerAssets",
                     "module": "babylonjs-viewer-assets"
                 },
-                "babylonIncluded": true
+                "babylonIncluded": true,
+                "noWatch": true,
+                "preventLoadLibrary": true
             }
         ],
         "build": {
             "srcOutputDirectory": "../../Viewer/",
+            "distOutputDirectory": "/viewer/",
             "dtsBundle": {
                 "name": "babylonjs-viewer-assets",
-                "baseDir": "../../Viewer/dist/build/src/assets/",
-                "main": "../../Viewer/dist/build/src/assets/index.d.ts",
-                "out": "../../../build/assets/babylon.viewer.assets.module.d.ts"
+                "main": "../../dist/preview release/viewer/build/src/assets/index.d.ts",
+                "out": "../../../../../../Viewer/build/assets/babylon.viewer.assets.module.d.ts"
             },
             "outputs": [
                 {
-                    "destination": [
+                    "destinations": [
                         {
                             "filename": "babylon.viewer.assets.js",
-                            "outputDirectory": "/../../Viewer/dist/build/assets/"
+                            "outputDirectory": "/../../Viewer/build/assets/"
                         }
                     ],
                     "minified": true

+ 1 - 1
Tools/Gulp/gulp-addDtsExport.js

@@ -46,7 +46,7 @@ declare module '${moduleName}' {
         }
 
         try {
-            file.contents = new Buffer(moduleExportsAddition + String(file.contents));
+            file.contents = Buffer.from(moduleExportsAddition + String(file.contents));
             this.push(file);
 
         } catch (err) {

+ 2 - 2
Tools/Gulp/gulp-addES6Exports.js

@@ -75,10 +75,10 @@ ${exportsText}
         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(baseModule)))));
+                file.contents = Buffer.from(optionalRequire.concat(Buffer.from(String(file.contents).concat(moduleExportAddition(baseModule)))));
             } else {
                 let pretext = subModule ? optionalRequire : '';
-                file.contents = new Buffer(pretext.concat(decorateAddition).concat(new Buffer(extendsAddition.concat(String(file.contents)).concat(moduleExportAddition(baseModule)))));
+                file.contents = Buffer.from(pretext.concat(decorateAddition).concat(Buffer.from(extendsAddition.concat(String(file.contents)).concat(moduleExportAddition(baseModule)))));
             }
             this.push(file);
         } catch (err) {

+ 1 - 1
Tools/Gulp/gulp-addModuleExports.js

@@ -99,7 +99,7 @@ if(typeof earcut !== 'undefined') {
 
         try {
             //if (config.externalUsingBabylon) {
-            file.contents = new Buffer(String('').concat(moduleExportAddition(varName)));
+            file.contents = Buffer.from(String('').concat(moduleExportAddition(varName)));
             /*} else {
                 let pretext = '';
                 file.contents = new Buffer(decorateAddition.concat(new Buffer(extendsAddition.concat(String('')).concat(moduleExportAddition(varName)))));

+ 1 - 1
Tools/Gulp/gulp-appendSrcToVariable.js

@@ -85,7 +85,7 @@ module.exports["${name}"] = data;
             cwd: firstFile.cwd,
             base: firstFile.base,
             path: joinedPath,
-            contents: new Buffer(content)
+            contents: Buffer.from(content)
         });
 
         this.push(joinedFile);

+ 1 - 1
Tools/Gulp/gulp-babylonModule.js

@@ -123,7 +123,7 @@ if(typeof require !== 'undefined'){
         }
 
         try {
-            file.contents = new Buffer(dependenciesText.concat(new Buffer(String(content).concat(exportsText))));
+            file.contents = Buffer.from(dependenciesText.concat(Buffer.from(String(content).concat(exportsText))));
             this.push(file);
         } catch (err) {
             this.emit('error', new gutil.PluginError('gulp-add-babylon-module', err, { fileName: file.path }));

+ 1 - 1
Tools/Gulp/gulp-decorateAndExtends.js

@@ -27,7 +27,7 @@ module.exports = function (varName, config) {
         }
 
         try {
-            file.contents = new Buffer(decorateAddition.concat(extendsAddition).concat(file.contents));
+            file.contents = Buffer.from(decorateAddition.concat(extendsAddition).concat(file.contents));
             this.push(file);
         } catch (err) {
             this.emit('error', new gutil.PluginError('gulp-decorate-and-extends', err, { fileName: file.path }));

+ 1 - 1
Tools/Gulp/gulp-dtsModuleSupport.js

@@ -84,7 +84,7 @@ module.exports = function (moduleName, inject, declarations, perFile, dependency
         }
 
         try {
-            file.contents = new Buffer(String(file.contents) + '\n' + importsString);
+            file.contents = Buffer.from(String(file.contents) + '\n' + importsString);
             this.push(file);
 
         } catch (err) {

+ 1 - 1
Tools/Gulp/gulp-es6ModuleExports.js

@@ -204,7 +204,7 @@ globalObject["BABYLON"] = BABYLON;
         }
 
         try {
-            file.contents = new Buffer(dependenciesText.concat(new Buffer(String(content).concat(exportsText))));
+            file.contents = Buffer.from(dependenciesText.concat(Buffer.from(String(content).concat(exportsText))));
             this.push(file);
         } catch (err) {
             this.emit('error', new gutil.PluginError('gulp-es6-module-exports', err, { fileName: file.path }));

+ 42 - 42
Tools/Gulp/gulp-removeShaderComments.js

@@ -8,12 +8,12 @@ var multiComment = 2;
 function uncomment(str, opts) {
     opts = opts || {};
 
-	var currentChar;
-	var nextChar;
-	var insideString = false;
-	var insideComment = 0;
-	var offset = 0;
-	var ret = '';
+    var currentChar;
+    var nextChar;
+    var insideString = false;
+    var insideComment = 0;
+    var offset = 0;
+    var ret = '';
 
     str = str.replace(/\r\n/g, '\n');
     str = str.replace(/[ \f\t\v]+/g, ' ');
@@ -34,45 +34,45 @@ function uncomment(str, opts) {
     str = str.replace(/, /g, ',');
     str = str.replace(/\n\n/g, '\n');
     str = str.replace(/\n /g, '\n');
-    
-	for (var i = 0; i < str.length; i++) {
-		currentChar = str[i];
-		nextChar = str[i + 1];
 
-		if (!insideComment && currentChar === '"') {
-			var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\';
-			if (!escaped) {
-				insideString = !insideString;
-			}
-		}
+    for (var i = 0; i < str.length; i++) {
+        currentChar = str[i];
+        nextChar = str[i + 1];
 
-		if (insideString) {
-			continue;
-		}
+        if (!insideComment && currentChar === '"') {
+            var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\';
+            if (!escaped) {
+                insideString = !insideString;
+            }
+        }
+
+        if (insideString) {
+            continue;
+        }
 
-		if (!insideComment && currentChar + nextChar === '//') {
-			ret += str.slice(offset, i);
-			offset = i;
-			insideComment = singleComment;
-			i++;
-		} else if (insideComment === singleComment && currentChar === '\n') {
-			insideComment = 0;
-			offset = i;
-		} else if (!insideComment && currentChar + nextChar === '/*') {
-			ret += str.slice(offset, i);
-			offset = i;
-			insideComment = multiComment;
-			i++;
-			continue;
-		} else if (insideComment === multiComment && currentChar + nextChar === '*/') {
-			i++;
-			insideComment = 0;
-			offset = i + 1;
-			continue;
-		}
-	}
+        if (!insideComment && currentChar + nextChar === '//') {
+            ret += str.slice(offset, i);
+            offset = i;
+            insideComment = singleComment;
+            i++;
+        } else if (insideComment === singleComment && currentChar === '\n') {
+            insideComment = 0;
+            offset = i;
+        } else if (!insideComment && currentChar + nextChar === '/*') {
+            ret += str.slice(offset, i);
+            offset = i;
+            insideComment = multiComment;
+            i++;
+            continue;
+        } else if (insideComment === multiComment && currentChar + nextChar === '*/') {
+            i++;
+            insideComment = 0;
+            offset = i + 1;
+            continue;
+        }
+    }
 
-	return ret + (insideComment ? '' : str.substr(offset));
+    return ret + (insideComment ? '' : str.substr(offset));
 }
 
 function gulpUncomment(options) {
@@ -88,7 +88,7 @@ function main(options, func) {
         if (file.isStream()) {
             cb(new PluginError("Remove Shader Comments", "Streaming not supported."));
         }
-        file.contents = new Buffer(func(file.contents.toString(), options));
+        file.contents = Buffer.from(func(file.contents.toString(), options));
         this.push(file);
         return cb();
     });

+ 52 - 46
Tools/Gulp/gulp-validateTypedoc.js

@@ -11,19 +11,19 @@ var supportsColor = require('color-support');
 
 var hasColors = supportsColor();
 
-var red =       hasColors ? '\x1b[31m' : '';
-var yellow =    hasColors ? '\x1b[33m' : '';
-var green =     hasColors ? '\x1b[32m' : '';
-var gray =      hasColors ? '\x1b[90m' : '';
-var white =     hasColors ? '\x1b[97m' : '';
-var clear =     hasColors ? '\x1b[0m' : '';
+var red = hasColors ? '\x1b[31m' : '';
+var yellow = hasColors ? '\x1b[33m' : '';
+var green = hasColors ? '\x1b[32m' : '';
+var gray = hasColors ? '\x1b[90m' : '';
+var white = hasColors ? '\x1b[97m' : '';
+var clear = hasColors ? '\x1b[0m' : '';
 
 var currentColor = undefined;
 
 function getTimestamp() {
     var time = new Date();
-    var timeInString = ("0" + time.getHours()).slice(-2) + ":" + 
-        ("0" + time.getMinutes()).slice(-2) + ":" + 
+    var timeInString = ("0" + time.getHours()).slice(-2) + ":" +
+        ("0" + time.getMinutes()).slice(-2) + ":" +
         ("0" + time.getSeconds()).slice(-2);
 
     if (currentColor) {
@@ -59,7 +59,7 @@ function err() {
     var time = getTimestamp();
     process.stderr.write(time + ' ');
     currentColor = undefined;
-    
+
     console.error.apply(console, arguments);
     return this;
 }
@@ -86,13 +86,13 @@ function Validate(validationBaselineFileName, namespaceName, validateNamingConve
     this.validateNamingConvention = validateNamingConvention;
     this.generateBaseLine = generateBaseLine;
 
-    this.previousResults = { };
+    this.previousResults = {};
     this.results = {
         errors: 0
     };
 }
 
-Validate.hasTag = function(node, tagName) {
+Validate.hasTag = function (node, tagName) {
     tagName = tagName.trim().toLowerCase();
 
     if (node.comment && node.comment.tags) {
@@ -106,7 +106,7 @@ Validate.hasTag = function(node, tagName) {
     return false;
 }
 
-Validate.position = function(node) {
+Validate.position = function (node) {
     if (!node.sources) {
         log(node);
     }
@@ -126,12 +126,12 @@ Validate.prototype.errorCallback = function (parent, node, nodeKind, category, t
     if (node === "toString") {
         node = "ToString";
     }
-    
+
     // Checks against previous results.
     var previousResults = this.previousResults[this.filePath];
     if (previousResults) {
         var previousRootName = parent ? parent : node;
-        var needCheck = true; 
+        var needCheck = true;
 
         if (Array.isArray(previousRootName)) {
             while (previousRootName.length > 1) {
@@ -165,7 +165,7 @@ Validate.prototype.errorCallback = function (parent, node, nodeKind, category, t
                             if (previousType) {
                                 // Early exit as it was already in the previous build.
                                 return;
-                            }    
+                            }
                         }
                     }
                 }
@@ -179,19 +179,19 @@ Validate.prototype.errorCallback = function (parent, node, nodeKind, category, t
     if (Array.isArray(rootName)) {
         while (rootName.length > 1) {
             var first = rootName.shift();
-            current = current[first] = current[first] || { };
+            current = current[first] = current[first] || {};
         }
         rootName = rootName.shift();
     }
 
-    current = current[rootName] = current[rootName] || { };
-    current = current[nodeKind] = current[nodeKind] || { };    
+    current = current[rootName] = current[rootName] || {};
+    current = current[nodeKind] = current[nodeKind] || {};
     if (parent) {
-        current = current[node] = current[node] || { };
+        current = current[node] = current[node] || {};
     }
-    current = current[category] = current[category] || { };
+    current = current[category] = current[category] || {};
     current = current[type] = true;
-    
+
     results.errors++;
 
     if (!this.generateBaseLine) {
@@ -216,7 +216,7 @@ Validate.prototype.add = function (filePath, content) {
     this.filePath = filePath && unixStylePath(filePath);
 
     if (!Buffer.isBuffer(content)) {
-        content = new Buffer(content);
+        content = Buffer.from(content);
     }
 
     var contentString = content.toString();
@@ -251,14 +251,6 @@ Validate.prototype.validateTypedoc = function (json) {
 Validate.prototype.validateTypedocNamespaces = function (namespaces) {
     var namespace = null;
 
-    var containerNode;
-    var childNode;
-    var children;
-    var signatures;
-    var signatureNode;
-    var tags;
-    var isPublic;
-
     // Check for BABYLON namespace
     for (var child in namespaces) {
         if (namespaces[child].name === this.namespaceName) {
@@ -272,23 +264,37 @@ Validate.prototype.validateTypedocNamespaces = function (namespaces) {
         return;
     }
 
-    // Check first sub module like BABYLON.Debug or BABYLON.GUI
-    if (namespace.children && namespace.children.length > 0) {
-        var firstChild = namespace.children[0];
-        if (firstChild.kindString === "Module") {
-            namespace = firstChild;
-        }
-    }
+    // Validate the namespace.
+    this.validateTypedocNamespace(namespace);
+}
+
+/**
+ * Validate classes and modules attach to a declaration file from a TypeDoc JSON file
+ */
+Validate.prototype.validateTypedocNamespace = function (namespace) {
+    var containerNode;
+    var childNode;
+    var children;
+    var signatures;
+    var signatureNode;
+    var tags;
+    var isPublic;
 
-    // Validate Classes
     for (var a in namespace.children) {
         containerNode = namespace.children[a];
 
+        // Validate Sub Module
+        if (containerNode.kindString === "Module") {
+            this.validateTypedocNamespace(containerNode);
+            continue;
+        }
+        // else Validate Classes
+
         // Account for undefined access modifiers.
         if (!containerNode.flags.isPublic &&
             !containerNode.flags.isPrivate &&
             !containerNode.flags.isProtected) {
-                containerNode.flags.isPublic = true;
+            containerNode.flags.isPublic = true;
         }
         isPublic = containerNode.flags.isPublic;
 
@@ -296,7 +302,7 @@ Validate.prototype.validateTypedocNamespaces = function (namespaces) {
         this.validateNaming(null, containerNode);
 
         // Validate Comments.
-        if (isPublic && !this.validateComment(containerNode)) {      
+        if (isPublic && !this.validateComment(containerNode)) {
             this.errorCallback(null,
                 containerNode.name,
                 containerNode.kindString,
@@ -402,7 +408,7 @@ Validate.prototype.validateTypedocNamespaces = function (namespaces) {
 /**
  * Validate that tags are recognized
  */
-Validate.prototype.validateTags = function(node) {
+Validate.prototype.validateTags = function (node) {
     var tags;
     var errorTags = [];
 
@@ -427,7 +433,7 @@ Validate.prototype.validateTags = function(node) {
 /**
  * Validate that a JSON node has the correct TypeDoc comments
  */
-Validate.prototype.validateComment = function(node) {
+Validate.prototype.validateComment = function (node) {
 
     // Return-only methods are allowed to just have a @return tag
     if ((node.kindString === "Call signature" || node.kindString === "Accessor") && !node.parameters && node.comment && node.comment.returns) {
@@ -447,7 +453,7 @@ Validate.prototype.validateComment = function(node) {
     // Return true for overwrited properties
     if (node.overwrites) {
         return true;
-    } 
+    }
 
     // Check comments.
     if (node.comment) {
@@ -469,7 +475,7 @@ Validate.prototype.validateComment = function(node) {
 /**
  * Validate comments for paramters on a node
  */
-Validate.prototype.validateParameters = function(containerNode, method, signature, parameters, isPublic) {
+Validate.prototype.validateParameters = function (containerNode, method, signature, parameters, isPublic) {
     var parametersNode;
     for (var parameter in parameters) {
         parametersNode = parameters[parameter];
@@ -498,7 +504,7 @@ Validate.prototype.validateParameters = function(containerNode, method, signatur
 /**
  * Validate naming conventions of a node
  */
-Validate.prototype.validateNaming = function(parent, node) {
+Validate.prototype.validateNaming = function (parent, node) {
     if (!this.validateNamingConvention) {
         return;
     }
@@ -706,7 +712,7 @@ function gulpValidateTypedoc(validationBaselineFileName, namespaceName, validate
 
         var action = generateBaseLine ? "baseline generation" : "validation";
         var self = this;
-        var error = function(message) {
+        var error = function (message) {
             generateBaseLine ? warn : err;
             if (generateBaseLine) {
                 warn(message);

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 467 - 240
Tools/Gulp/gulpfile.js


+ 29 - 37
Tools/Gulp/package.json

@@ -9,38 +9,32 @@
     "readme": "https://github.com/BabylonJS/Babylon.js/edit/master/readme.md",
     "license": "(Apache-2.0)",
     "devDependencies": {
-        "@types/node": "^8.9.4",
-        "base64-font-loader": "0.0.4",
+        "@types/node": "^8.10.21",
         "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.2.4",
-        "exports-loader": "^0.6.4",
-        "gulp": "^3.8.11",
-        "gulp-changed-in-place": "2.0.3",
+        "css-loader": "^1.0.0",
+        "deepmerge": "^2.1.1",
+        "del": "3.0.0",
+        "gulp": "^4.0.0",
         "gulp-clean-ts-extends": "~0.1.1",
-        "gulp-concat": "~2.5.2",
+        "gulp-concat": "~2.6.1",
         "gulp-content-to-variable": "^0.1.0",
-        "gulp-debug": "^3.2.0",
-        "gulp-expect-file": "^0.0.7",
-        "gulp-optimize-js": "^1.0.2",
-        "gulp-rename": "~1.2.2",
-        "gulp-replace": "~0.5.3",
-        "gulp-sass": "3.1.0",
-        "gulp-sourcemaps": "~1.9.1",
-        "gulp-typedoc": "^2.1.2",
-        "gulp-typescript": "^3.2.4",
-        "gulp-uglify": "^2.1.2",
-        "gulp-util": "~3.0.4",
+        "gulp-debug": "^4.0.0",
+        "gulp-expect-file": "^1.0.0",
+        "gulp-optimize-js": "^1.1.0",
+        "gulp-rename": "^1.4.0",
+        "gulp-replace": "~1.0.0",
+        "gulp-sass": "^4.0.1",
+        "gulp-sourcemaps": "~2.6.4",
+        "gulp-typedoc": "^2.2.0",
+        "gulp-typescript": "4.0.2",
+        "gulp-uglify": "^3.0.1",
         "gulp-webserver": "^0.9.1",
         "handlebars": "^4.0.11",
         "html-loader": "^0.5.5",
-        "imports-loader": "^0.7.1",
         "json-loader": "^0.5.7",
-        "karma": "^2.0.0",
+        "karma": "^2.0.5",
         "karma-browserstack-launcher": "^1.3.0",
         "karma-chai": "^0.1.0",
         "karma-chrome-launcher": "^2.2.0",
@@ -48,25 +42,23 @@
         "karma-mocha": "^1.3.0",
         "karma-phantomjs-launcher": "^1.0.4",
         "karma-sinon": "^1.0.5",
-        "merge2": "~0.3.5",
+        "merge2": "~1.2.2",
         "minimist": "^1.2.0",
-        "mocha": "^4.0.1",
-        "phantomjs": "^2.1.7",
-        "run-sequence": "~1.1.0",
-        "sinon": "^4.3.0",
-        "style-loader": "^0.13.2",
-        "through2": "~0.6.5",
-        "ts-loader": "^2.3.7",
-        "typedoc": "^0.9.0",
-        "typescript": "~2.8.1",
-        "webpack-stream": "^4.0.1"
+        "mocha": "^5.2.0",
+        "phantomjs-prebuilt": "^2.1.16",
+        "sinon": "^6.1.4",
+        "through2": "~2.0.3",
+        "ts-loader": "^4.4.2",
+        "typedoc": "^0.11.0",
+        "typescript": "^2.9.2",
+        "webpack": "^4.16.2",
+        "webpack-stream": "^5.0.0"
     },
     "scripts": {
-        "install": "npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && npm --prefix ../../Viewer/tests/ install ../../Viewer/tests/ && cd ../../Viewer && npm install && cd ../Tools/Gulp/ && gulp deployLocalDev"
+        "install": "cd ../../gui && npm install && cd ../Tools/Gulp/ &&  cd ../../inspector && npm install && cd ../Tools/Gulp/ && npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && npm --prefix ../../Viewer/tests/ install ../../Viewer/tests/ && cd ../../Viewer && npm install && cd ../Tools/Gulp/ && gulp deployLocalDev"
     },
     "dependencies": {
         "dts-bundle": "^0.7.3",
-        "gulp-clean": "^0.4.0",
-        "npm": "^5.8.0"
+        "gulp-clean": "^0.4.0"
     }
 }

+ 51 - 19
Tools/Gulp/processViewerDeclaration.js

@@ -1,4 +1,13 @@
-module.exports = function (data) {
+module.exports = function (data, options) {
+
+    /*
+    {
+        packageName: string,
+        moduleName: string,
+        importsToRemove: Array<string>,
+        classMap
+    }
+    */
 
     var str = "" + data;
 
@@ -6,35 +15,58 @@ module.exports = function (data) {
     // str = str.replace(/declare module 'babylonjs-viewer\/' {((?!(declare))(.|\n))*\n}/g, '');
 
     let lines = str.split('\n');
-    var firstIndex = lines.findIndex((line => { return line.indexOf("'babylonjs-viewer/'") !== -1 }));
+    var firstIndex = lines.findIndex((line => { return line.indexOf(`'${options.packageName}/'`) !== -1 }));
     var lastIndex = lines.findIndex(((line, idx) => { return line.trim() === '}' && idx > firstIndex }));
     lines.splice(firstIndex, lastIndex - firstIndex + 1);
     str = lines.join('\n');
 
-    str = str.replace(/declare module (.*) {/g, 'declare module BabylonViewer {').replace("import * as BABYLON from 'babylonjs';", "");
-    str = str.replace(/import {(.*)} from ['"]babylonjs-viewer(.*)['"];/g, '').replace(/import 'babylonjs-loaders';/, '').replace(/import 'pep';/, '');
+    str = str.replace(/declare module (.*) {/g, `declare module ${options.moduleName} {`);
+
+    str = str.replace("import * as BABYLON from 'babylonjs';", "");
+    let regexp = new RegExp(`import {(.*)} from ['"]${options.packageName}(.*)['"];`, 'g');
+    str = str.replace(regexp, '');
+
+    if (options.importsToRemove) {
+        while (options.importsToRemove.length) {
+            let remove = options.importsToRemove.pop();
+            str = str.replace(new RegExp(`import '${remove}';`), '');
+        }
+    }
 
     //find all used BABYLON and BABYLON-Loaders classes:
 
-    var babylonRegex = /import {(.*)} from ['"](babylonjs|babylonjs-loaders)['"];/g
+    if ((options.classMap)) {
+        Object.keys(options.classMap).forEach(package => {
+            var babylonRegex = new RegExp(`import {(.*)} from ['"](${package})['"];`, "g");
 
-    var match = babylonRegex.exec(str);
-    let classes = new Set();
-    while (match != null) {
-        if (match[1]) {
-            match[1].split(",").forEach(element => {
-                classes.add(element.trim());
+            var match = babylonRegex.exec(str);
+            let classes = new Set();
+            while (match != null) {
+                if (match[1]) {
+                    match[1].split(",").forEach(element => {
+                        classes.add(element.trim());
+                    });
+                }
+                match = babylonRegex.exec(str);
+            }
+            str = str.replace(babylonRegex, '');
+            classes.forEach(cls => {
+                let rg = new RegExp(`([ <])(${cls})([^\\w])`, "g")
+                str = str.replace(rg, `$1${options.classMap[package]}.$2$3`);
             });
-        }
-        match = babylonRegex.exec(str);
+        })
     }
-    str = str.replace(babylonRegex, '');
-    classes.forEach(cls => {
-        let rg = new RegExp(`([ <])(${cls})([^\\w])`, "g")
-        str = str.replace(rg, "$1BABYLON.$2$3");
-    });
 
-    str = str.replace(/export {(.*)};/g, '')
+    str = str.replace(/export {(.*)};/g, '');
+
+    str = str.replace(/import (.*);/g, "");
+
+    str = str.split("\n").filter(line => line.trim()).filter(line => line.indexOf("export * from") === -1).join("\n");
+
+    //empty declare regex
+    let emptyDeclareRegexp = new RegExp("declare module " + options.moduleName + " {\n}", "g");
+
+    str = str.replace(emptyDeclareRegexp, "");
 
     return str;
 }

+ 15 - 5
Tools/Publisher/index.js

@@ -8,6 +8,8 @@ let basePath = '../../dist/preview release';
 // This can be changed when we have a new major release.
 let minimumDependency = '>=3.2.0-alpha';
 
+process.env.PATH += (path.delimiter + path.join(__dirname, 'node_modules', '.bin'));
+
 let packages = [
     {
         name: 'core',
@@ -51,12 +53,13 @@ let packages = [
         required: [
             basePath + '/viewer/readme.md',
             basePath + '/viewer/package.json',
-            basePath + '/viewer/babylon.viewer.js'
+            basePath + '/viewer/babylon.viewer.js',
+            basePath + '/viewer/babylon.viewer.max.js'
         ]
     },
     {
         name: 'viewer-assets',
-        path: basePath + '/../../Viewer/dist/build/assets/',
+        path: basePath + '/../../Viewer/build/assets/',
         required: [
             basePath + '/../../Viewer/assets/readme.md',
             basePath + '/../../Viewer/assets/package.json',
@@ -215,7 +218,7 @@ function processCore(package, version) {
 
 function processViewer(package, version) {
 
-    let buildPath = package.path + "dist/build/src/";
+    let buildPath = package.path + "build/src/";
     let projectPath = '../../Viewer';
 
     if (package.required) {
@@ -228,7 +231,11 @@ function processViewer(package, version) {
 
     // build the viewer
     console.log("executing " + 'tsc -p ' + projectPath);
-    shelljs.exec('tsc -p ' + projectPath);
+
+    let tscCompile = shelljs.exec('tsc -p ' + projectPath);
+    if (tscCompile.code !== 0) {
+        throw new Error("tsc compilation failed");
+    }
 
     let packageJson = require(buildPath + '/package.json');
 
@@ -257,7 +264,10 @@ function publish(version, packageName, basePath) {
 
     //publish the respected package
     console.log("executing " + 'npm publish \"' + basePath + "\"" + ' ' + tagDef);
-    shelljs.exec('npm publish \"' + basePath + "\"" + ' ' + tagDef);
+    if (process.argv.indexOf('--no-publish') === -1) {
+        shelljs.exec('npm publish \"' + basePath + "\"" + ' ' + tagDef);
+    }
+
 }
 
 function getFiles(dir, files_) {

+ 18 - 17
Tools/Publisher/package.json

@@ -1,19 +1,20 @@
 {
-  "name": "banylonjs-publisher",
-  "version": "1.0.0",
-  "description": "Publishing babylon's packages automatically",
-  "main": "index.js",
-  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
-  },
-  "author": "Raanan Weber",
-  "license": "ISC",
-  "dependencies": {
-    "fs-extra": "^5.0.0",
-    "prompt": "^1.0.0",
-    "shelljs": "^0.7.8"
-  },
-  "devDependencies": {
-    "gulp": "^3.9.1"
-  }
+    "name": "banylonjs-publisher",
+    "version": "1.0.0",
+    "description": "Publishing babylon's packages automatically",
+    "main": "index.js",
+    "scripts": {
+        "test": "echo \"Error: no test specified\" && exit 1"
+    },
+    "author": "Raanan Weber",
+    "license": "ISC",
+    "dependencies": {
+        "fs-extra": "^5.0.0",
+        "prompt": "^1.0.0",
+        "shelljs": "^0.7.8",
+        "typescript": "^2.9.2"
+    },
+    "devDependencies": {
+        "gulp": "^4.0.0"
+    }
 }

+ 139 - 0
Tools/WebpackShaderLoader/index.js

@@ -0,0 +1,139 @@
+//modified https://github.com/grieve/webpack-glsl-loader/blob/master/index.js
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+
+function parse(loader, source, context, cb) {
+    var imports = [];
+    var importPattern = /@import ([.\/\w_-]+);/gi;
+    var match = importPattern.exec(source);
+
+    while (match != null) {
+        imports.push({
+            key: match[1],
+            target: match[0],
+            content: ''
+        });
+        match = importPattern.exec(source);
+    }
+
+    source = uncomment(source);
+
+    processImports(loader, source, context, imports, cb);
+}
+
+var singleComment = 1;
+var multiComment = 2;
+
+function uncomment(str) {
+
+    var currentChar;
+    var nextChar;
+    var insideString = false;
+    var insideComment = 0;
+    var offset = 0;
+    var ret = '';
+
+    str = str.replace(/\r\n/g, '\n');
+    str = str.replace(/[ \f\t\v]+/g, ' ');
+    str = str.replace(/^\s*\n/gm, '');
+    str = str.replace(/ \+ /g, '+');
+    str = str.replace(/ \- /g, '-');
+    str = str.replace(/ \/ /g, '/');
+    str = str.replace(/ \* /g, '*');
+    str = str.replace(/ > /g, '>');
+    str = str.replace(/ < /g, '<');
+    str = str.replace(/ >= /g, '>=');
+    str = str.replace(/ <= /g, '<=');
+    str = str.replace(/ \+= /g, '+=');
+    str = str.replace(/ \-= /g, '-=');
+    str = str.replace(/ \/= /g, '/=');
+    str = str.replace(/ \*= /g, '*=');
+    str = str.replace(/ = /g, '=');
+    str = str.replace(/, /g, ',');
+    str = str.replace(/\n\n/g, '\n');
+    str = str.replace(/\n /g, '\n');
+
+    for (var i = 0; i < str.length; i++) {
+        currentChar = str[i];
+        nextChar = str[i + 1];
+
+        if (!insideComment && currentChar === '"') {
+            var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\';
+            if (!escaped) {
+                insideString = !insideString;
+            }
+        }
+
+        if (insideString) {
+            continue;
+        }
+
+        if (!insideComment && currentChar + nextChar === '//') {
+            ret += str.slice(offset, i);
+            offset = i;
+            insideComment = singleComment;
+            i++;
+        } else if (insideComment === singleComment && currentChar === '\n') {
+            insideComment = 0;
+            offset = i;
+        } else if (!insideComment && currentChar + nextChar === '/*') {
+            ret += str.slice(offset, i);
+            offset = i;
+            insideComment = multiComment;
+            i++;
+            continue;
+        } else if (insideComment === multiComment && currentChar + nextChar === '*/') {
+            i++;
+            insideComment = 0;
+            offset = i + 1;
+            continue;
+        }
+    }
+
+    return ret + (insideComment ? '' : str.substr(offset));
+}
+
+function processImports(loader, source, context, imports, cb) {
+    if (imports.length === 0) {
+        return cb(null, source);
+    }
+
+    var imp = imports.pop();
+
+    loader.resolve(context, imp.key + '.fx', function (err, resolved) {
+        if (err) {
+            return cb(err);
+        }
+
+        loader.addDependency(resolved);
+        fs.readFile(resolved, 'utf-8', function (err, src) {
+            if (err) {
+                return cb(err);
+            }
+
+            parse(loader, src, path.dirname(resolved), function (err, bld) {
+                if (err) {
+                    return cb(err);
+                }
+
+                source = source.replace(imp.target, bld);
+                processImports(loader, source, context, imports, cb);
+            });
+        });
+    });
+}
+
+module.exports = function (source) {
+    this.cacheable();
+    var cb = this.async();
+    parse(this, source, this.context, function (err, bld) {
+        if (err) {
+            return cb(err);
+        }
+
+        cb(null, 'module.exports = ' + JSON.stringify(bld));
+    });
+};

BIN=BIN
Viewer/assets/babylon.woff


+ 36 - 22
Viewer/assets/templates/default/navbar.html

@@ -139,11 +139,29 @@
         content: "\E740";
     }
 
+    /*
+    A few browsers dont support combining the next rule to one. Redudant.
+    */
+
+    viewer.in-fullscreen .fullscreen-icon:after {
+        content: "\E73F";
+    }
+
     .help-icon:after {
         font-size: 16px;
         content: "\EF4E";
     }
 
+    viewer.in-vr .vr-icon:after {
+        font-size: 16px;
+        content: "\E7F4";
+    }
+
+    .vr-icon:after {
+        font-size: 16px;
+        content: "\F119";
+    }
+
     .progress-control {
         display: flex;
         flex: 1;
@@ -408,21 +426,13 @@
 </style>
 {{/if}} {{/if}} {{#if disableOnFullscreen}}
 <style>
-    viewer:fullscreen nav-bar {
-        display: none;
-    }
-
-    viewer:-moz-full-screen nav-bar {
-        display: none;
-    }
-
-    viewer:-webkit-full-screen nav-bar {
+    viewer.in-fullscreen nav-bar {
         display: none;
     }
 </style>
 {{/if}}
 
-<div class="nav-container" id="navbar-control">
+<div class="nav-container navbar-control">
     {{#unless hideLogo}}
     <div class="logo-button" title="{{logoText}}">
         {{#if logoLink}}
@@ -435,7 +445,7 @@
     {{/unless}}{{#unless (or (not animations) hideAnimations)}}
     <div class="animation-control">
         <div class="types">
-            <button class="flex-container animation-buttons" id="types-button">
+            <button class="flex-container types-button animation-buttons">
                 <!-- <div> -->
                 <span class="icon types-icon"></span>
                 <span class="control-text animation-label">{{selectedAnimationName}}</span>
@@ -447,34 +457,34 @@
             </button>
             <div class="menu-options">
                 {{#each animations}} {{#unless (eq ../selectedAnimation (add @index 1))}}
-                <button class="flex-container animation-buttons" id="label-option-button" data-value="{{this}}">
+                <button class="flex-container label-option-button animation-buttons" data-value="{{this.value}} ">
                     <!-- <div> -->
                     <span class="icon types-icon"></span>
-                    <span class="control-text animation-label">{{this}}</span>
+                    <span class="control-text animation-label">{{this.label}}</span>
                     <span class="control-text animation-number">{{add @index 1}}</span>
                     <!-- </div> -->
                 </button>
                 {{/unless}} {{/each}}
             </div>
         </div>
-        <div class="progress-control" id="progress-control">
-            <button class="play-pause" id="play-pause-button">
+        <div class="progress-control">
+            <button class="play-pause play-pause-button">
                 {{#if paused}}
                 <span class="icon play-icon"></span>
                 {{else}}
                 <span class="icon pause-icon"></span>
                 {{/if}}
             </button>
-            <input class="progress-wrapper" id="progress-wrapper" type="range" min="0" max="100" step="0.01">
+            <input class="progress-wrapper" type="range" min="0" max="100" step="0.01">
         </div>
         <div class="speed">
-            <button class="flex-container" id="speed-button">
+            <button class="flex-container speed-button">
                 <span class="control-text speed-text">{{selectedSpeed}}</span>
                 <span class="icon up-icon"></span>
             </button>
             <div class="menu-options">
                 {{#eachInMap speedList}} {{#unless (eq ../selectedSpeed id)}}
-                <button class="flex-container" id="speed-option-button" data-value="{{value}}">
+                <button class="flex-container speed-option-button" data-value="{{value}}">
                     <span class="control-text speed-text">{{id}}</span>
                 </button>
                 {{/unless}} {{/eachInMap}}
@@ -483,12 +493,16 @@
     </div>
     {{/unless}}
     <div class="default-control">
-        {{#unless hideHelp}}
-        <button class="help" id="help-button" title="Help">
+        {{#unless hideVr}}
+        <button class="vr vr-button" title="{{text.vrButton}} ">
+            <span class="icon vr-icon"></span>
+        </button>
+        {{/unless}}{{#unless hideHelp}}
+        <button class="help help-button" title="{{text.helpButton}} ">
             <span class="icon help-icon"></span>
         </button>
-        {{/unless}} {{#unless hideFullScreen}}
-        <button class="fullscreen" id="fullscreen-button" title="Fullscreen">
+        {{/unless}} {{#unless hideFullscreen}}
+        <button class="fullscreen fullscreen-button" title="{{text.fullscreenButton}} ">
             <span class="icon fullscreen-icon"></span>
         </button>
         {{/unless}}

+ 1 - 1
Viewer/assets/templates/default/overlay.html

@@ -3,7 +3,7 @@
         position: absolute;
         z-index: 99;
         opacity: 0;
-        display: flex;
+        display: none;
         justify-content: center;
         align-items: center;
         -webkit-transition: opacity 1s ease;

BIN=BIN
Viewer/dist/assets/environment/EnvMap_3.0-256.env


BIN=BIN
Viewer/dist/babylon.woff


+ 7 - 0
Viewer/dist/external/msft/config.json

@@ -21,5 +21,12 @@
             "g": 0.9607843137254902,
             "b": 0.9607843137254902
         }
+    },
+    "templates": {
+        "navBar": {
+            "params": {
+                "hideHdButton": false
+            }
+        }
     }
 }

+ 25 - 0
Viewer/dist/printExample.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html lang="en">
+
+    <head>
+        <meta charset="UTF-8">
+        <meta name="viewport" content="width=device-width, initial-scale=1.0">
+        <meta http-equiv="X-UA-Compatible" content="ie=edge">
+        <title>BabylonJS Viewer - 3D Print usage</title>
+        <style>
+            babylon {
+                width: 800px;
+                height: 500px;
+            }
+        </style>
+    </head>
+
+    <body>
+        <babylon templates.nav-bar.params.hide-print="false">
+            <model url="https://playground.babylonjs.com/scenes/BoomBox.glb">
+            </model>
+        </babylon>
+        <script src="viewer.js"></script>
+    </body>
+
+</html>

+ 6 - 4
Viewer/package.json

@@ -27,15 +27,17 @@
         "@types/node": "^8.9.4",
         "base64-font-loader": "0.0.4",
         "base64-image-loader": "^1.2.1",
+        "base64-inline-loader": "^1.1.1",
         "deepmerge": "^2.1.1",
         "handlebars": "^4.0.11",
         "html-loader": "^0.5.5",
         "json-loader": "^0.5.7",
-        "ts-loader": "^2.3.7",
-        "typescript": "^2.7.2",
+        "ts-loader": "^4.4.0",
+        "typescript": "^2.9.2",
         "uglifyjs-webpack-plugin": "^1.2.2",
-        "webpack": "^3.11.0",
-        "webpack-dev-server": "^2.11.2"
+        "webpack": "^4.16.0",
+        "webpack-cli": "^3.0.8",
+        "webpack-dev-server": "^3.1.4"
     },
     "dependencies": {
         "pepjs": "^0.4.3"

+ 10 - 2
Viewer/src/configuration/configuration.ts

@@ -1,5 +1,6 @@
-import { EngineOptions, IGlowLayerOptions, DepthOfFieldEffectBlurLevel } from 'babylonjs';
-import { IObserversConfiguration, IModelConfiguration, ISceneConfiguration, ISceneOptimizerConfiguration, ICameraConfiguration, ISkyboxConfiguration, IGroundConfiguration, ILightConfiguration, IDefaultRenderingPipelineConfiguration, ITemplateConfiguration } from './interfaces';
+import { EngineOptions } from 'babylonjs';
+import { ICameraConfiguration, IDefaultRenderingPipelineConfiguration, IGroundConfiguration, ILightConfiguration, IModelConfiguration, IObserversConfiguration, ISceneConfiguration, ISceneOptimizerConfiguration, ISkyboxConfiguration, ITemplateConfiguration, IVRConfiguration } from './interfaces';
+import { IEnvironmentMapConfiguration } from './interfaces/environmentMapConfiguration';
 
 export function getConfigurationKey(key: string, configObject: any) {
     let splits = key.split('.');
@@ -54,6 +55,7 @@ export interface ViewerConfiguration {
         disableResize?: boolean;
         engineOptions?: EngineOptions;
         adaptiveQuality?: boolean;
+        hdEnabled?: boolean;
     },
     //templateStructure?: ITemplateStructure,
     templates?: {
@@ -79,6 +81,10 @@ export interface ViewerConfiguration {
         [propName: string]: boolean | undefined;
     };
 
+    environmentMap?: IEnvironmentMapConfiguration
+
+    vr?: IVRConfiguration;
+
     // features that are being tested.
     // those features' syntax will change and move out! 
     // Don't use in production (or be ready to make the changes :) )
@@ -91,8 +97,10 @@ export interface ViewerConfiguration {
             specular?: { r: number, g: number, b: number };
         }
         hideLoadingDelay?: number;
+        /** Deprecated */
         assetsRootURL?: string;
         environmentMainColor?: { r: number, g: number, b: number };
+        /** Deprecated */
         environmentMap?: {
             /**
              * Environment map texture path in relative to the asset folder.

+ 21 - 3
Viewer/src/configuration/configurationCompatibility.ts

@@ -7,8 +7,6 @@ import { ViewerConfiguration, getConfigurationKey } from './configuration'
  */
 export function processConfigurationCompatibility(configuration: ViewerConfiguration) {
 
-
-
     if (configuration.camera) {
         // camera contrast -> image processing contrast
         if (configuration.camera.contrast !== undefined) {
@@ -30,6 +28,26 @@ export function processConfigurationCompatibility(configuration: ViewerConfigura
                 setKeyInObject(configuration, "scene.imageProcessingConfiguration.isEnabled", true);
             }
         }
+
+        if (configuration.scene.mainColor) {
+            setKeyInObject(configuration, "environmentMap.mainColor", configuration.scene.mainColor, true);
+        }
+    }
+
+    if (configuration.model && typeof configuration.model === 'object') {
+        // castShadows === castShadow
+        if ((<any>configuration.model).castShadows !== undefined && configuration.model.castShadow === undefined) {
+            configuration.model.castShadow = (<any>configuration.model).castShadows;
+        }
+    }
+
+    if (configuration.lab) {
+        if (configuration.lab.assetsRootURL) {
+            setKeyInObject(configuration, "scene.assetsRootURL", configuration.lab.assetsRootURL, true);
+        }
+        if (configuration.lab.environmentMap) {
+            setKeyInObject(configuration, "environmentMap", configuration.lab.environmentMap, true);
+        }
     }
 }
 
@@ -45,4 +63,4 @@ function setKeyInObject(object: any, keys: string, value: any, shouldOverwrite?:
     });
     if (curObj[lastKey] !== undefined && !shouldOverwrite) return;
     curObj[lastKey] = value;
-}
+}

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

@@ -1,5 +1,5 @@
 import { ViewerConfiguration } from './configuration';
-import { Color3 } from 'babylonjs';
+import { Color3, Scene } from 'babylonjs';
 
 export class ConfigurationContainer {
 
@@ -9,4 +9,5 @@ export class ConfigurationContainer {
 
     public mainColor: Color3 = Color3.White();
     public reflectionColor: Color3 = Color3.White();
+    public scene?: Scene;
 }

+ 21 - 0
Viewer/src/configuration/interfaces/environmentMapConfiguration.ts

@@ -0,0 +1,21 @@
+export interface IEnvironmentMapConfiguration {
+    /**
+     * Environment map texture path in relative to the asset folder.
+     */
+    texture: string;
+
+    /**
+     * Default rotation to apply to the environment map.
+     */
+    rotationY: number;
+
+    /**
+     * Tint level of the main color on the environment map.
+     */
+    tintLevel: number;
+
+    /**
+     * The environment's main color.
+     */
+    mainColor?: { r?: number, g?: number, b?: number };
+}

+ 3 - 1
Viewer/src/configuration/interfaces/index.ts

@@ -10,4 +10,6 @@ export * from './observersConfiguration';
 export * from './sceneConfiguration';
 export * from './sceneOptimizerConfiguration';
 export * from './skyboxConfiguration';
-export * from './templateConfiguration';
+export * from './templateConfiguration';
+export * from './vrConfiguration';
+export * from './environmentMapConfiguration';

+ 3 - 1
Viewer/src/configuration/interfaces/sceneConfiguration.ts

@@ -5,6 +5,7 @@ import { IGlowLayerOptions } from "babylonjs";
 export interface ISceneConfiguration {
     debug?: boolean;
     clearColor?: { r: number, g: number, b: number, a: number };
+    /** Deprecated, use environmentMap.mainColor instead. */
     mainColor?: { r?: number, g?: number, b?: number };
     imageProcessingConfiguration?: IImageProcessingConfiguration;
     environmentTexture?: string;
@@ -36,5 +37,6 @@ export interface ISceneConfiguration {
         spritesEnabled?: boolean;
         skeletonsEnabled?: boolean;
         audioEnabled?: boolean;
-    }
+    };
+    assetsRootURL?: string;
 }

+ 13 - 0
Viewer/src/configuration/interfaces/vrConfiguration.ts

@@ -0,0 +1,13 @@
+import { VRExperienceHelperOptions } from "babylonjs";
+
+export interface IVRConfiguration {
+    disabled?: boolean;
+    objectScaleFactor?: number;
+    disableInteractions?: boolean;
+    disableTeleportation?: boolean;
+    overrideFloorMeshName?: string;
+    vrOptions?: VRExperienceHelperOptions;
+    modelHeightCorrection?: number | boolean;
+    rotateUsingControllers?: boolean; // experimental feature
+    cameraPosition?: { x: number, y: number, z: number }
+}

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

@@ -33,8 +33,9 @@ export class ConfigurationLoader {
     public loadConfiguration(initConfig: ViewerConfiguration = {}, callback?: (config: ViewerConfiguration) => void): Promise<ViewerConfiguration> {
 
         let loadedConfig: ViewerConfiguration = deepmerge({}, initConfig);
+        this._processInitialConfiguration(loadedConfig);
 
-        let extendedConfiguration = getConfigurationType(loadedConfig.extends || "");
+        let extendedConfiguration = getConfigurationType(loadedConfig.extends || "extended");
 
         if (loadedConfig.configuration) {
 
@@ -94,6 +95,20 @@ export class ConfigurationLoader {
         this._loadRequests.length = 0;
     }
 
+    /**
+     * This function will process the initial configuration and make needed changes for the viewer to work.
+     * @param config the mutable(!) initial configuration to process
+     */
+    private _processInitialConfiguration(config: ViewerConfiguration) {
+        if (config.model) {
+            if (typeof config.model === "string") {
+                config.model = {
+                    url: config.model
+                }
+            }
+        }
+    }
+
     private _loadFile(url: string): Promise<any> {
         let cacheReference = this._configurationCache;
         if (this._enableCache && cacheReference[url]) {

+ 4 - 0
Viewer/src/configuration/mappers.ts

@@ -52,6 +52,10 @@ class HTMLMapper implements IMapper {
                         val = true;
                     } else if (val === "false") {
                         val = false;
+                    } else if (val === "undefined") {
+                        val = undefined;
+                    } else if (val === "null") {
+                        val = null;
                     } else {
                         var isnum = !isNaN(parseFloat(val)) && isFinite(val);///^\d+$/.test(val);
                         if (isnum) {

+ 15 - 6
Viewer/src/configuration/types/default.ts

@@ -49,18 +49,28 @@ export let defaultConfiguration: ViewerConfiguration = {
                 logoText: 'BabylonJS',
                 logoLink: 'https://babylonjs.com',
                 hideHelp: true,
+                hideHd: true,
+                hideVr: true,
+                hidePrint: true,
                 disableOnFullscreen: false,
+                text: {
+                    hdButton: "Toggle HD",
+                    fullscreenButton: "Toggle Fullscreen",
+                    helpButton: "Help",
+                    vrButton: "Toggle VR",
+                    printButton: "3D Print Object"
+                }
             },
             events: {
                 pointerdown: {
-                    'navbar-control': true,
-                    'help-button': true
+                    '.navbar-control': true,
+                    '.help-button': true
                 },
                 input: {
-                    'progress-wrapper': true
+                    '.progress-wrapper': true
                 },
                 pointerup: {
-                    'progress-wrapper': true
+                    '.progress-wrapper': true
                 }
             }
         },
@@ -95,8 +105,7 @@ export let defaultConfiguration: ViewerConfiguration = {
             bouncing: {
                 type: 1
             }
-        },
-        wheelPrecision: 200,
+        }
     },
     skybox: {
     },

+ 14 - 14
Viewer/src/configuration/types/extended.ts

@@ -62,7 +62,7 @@ export let extendedConfiguration: ViewerConfiguration = {
             intensity: 7,
             intensityMode: 0,
             radius: 0.6,
-            range: 0.6,
+            range: 4.4,
             spotAngle: 60,
             diffuse: {
                 r: 1,
@@ -101,7 +101,7 @@ export let extendedConfiguration: ViewerConfiguration = {
             intensity: 7,
             intensityMode: 0,
             radius: 0.4,
-            range: 0.4,
+            range: 5.8,
             spotAngle: 57,
             diffuse: {
                 r: 1,
@@ -132,7 +132,7 @@ export let extendedConfiguration: ViewerConfiguration = {
             intensity: 1,
             intensityMode: 0,
             radius: 0.5,
-            range: 0.5,
+            range: 6,
             spotAngle: 42.85,
             diffuse: {
                 r: 0.8,
@@ -252,11 +252,7 @@ export let extendedConfiguration: ViewerConfiguration = {
                 highlightsSaturation: 0
             }
         },
-        mainColor: {
-            r: 0.8823529411764706,
-            g: 0.8823529411764706,
-            b: 0.8823529411764706
-        }
+        assetsRootURL: 'https://viewer.babylonjs.com/assets/environment/'
     },
     loaderPlugins: {
         extendedMaterial: true,
@@ -301,13 +297,17 @@ export let extendedConfiguration: ViewerConfiguration = {
         castShadow: true,
         receiveShadows: true
     },
+    environmentMap: {
+        texture: "EnvMap_3.0-256.env",
+        rotationY: 3,
+        tintLevel: 0.4,
+        mainColor: {
+            r: 0.8823529411764706,
+            g: 0.8823529411764706,
+            b: 0.8823529411764706
+        }
+    },
     lab: {
-        assetsRootURL: 'https://viewer.babylonjs.com/assets/environment/',
-        environmentMap: {
-            texture: "EnvMap_2.0-256.env",
-            rotationY: 3,
-            tintLevel: 0.4
-        },
         defaultRenderingPipelines: {
             bloomEnabled: true,
             bloomThreshold: 1.0,

+ 4 - 4
Viewer/src/configuration/types/index.ts

@@ -28,17 +28,17 @@ let getConfigurationType = function (types: string): ViewerConfiguration {
             case 'shadowSpotLight':
                 config = deepmerge(config, shadowSpotlLightConfiguration);
                 break;
-            case 'extended':
-                config = deepmerge(config, extendedConfiguration);
+            case 'default':
+                config = deepmerge(config, defaultConfiguration);
                 break;
             case 'minimal':
                 config = deepmerge(config, minimalConfiguration);
                 break;
             case 'none':
                 break;
-            case 'default':
+            case 'extended':
             default:
-                config = deepmerge(config, defaultConfiguration);
+                config = deepmerge(config, extendedConfiguration);
                 break;
         }
 

+ 2 - 2
Viewer/src/helper/index.ts

@@ -40,8 +40,8 @@ export function camelToKebab(str) {
  * @param config the configuration object that will extend the object
  */
 export function extendClassWithConfig(object: any, config: any) {
-    if (!config) return;
-    Object.keys(config).forEach(key => {
+    if (!config || typeof config !== 'object') return;
+    Object.keys(config).forEach(function (key) {
         if (key in object && typeof object[key] !== 'function') {
             // if (typeof object[key] === 'function') return;
             // if it is an object, iterate internally until reaching basic types

+ 3 - 1
Viewer/src/index.ts

@@ -8,6 +8,8 @@ import { ModelLoader } from './loader/modelLoader';
 import { ViewerModel, ModelState } from './model/viewerModel';
 import { AnimationPlayMode, AnimationState } from './model/modelAnimation';
 import { ILoaderPlugin } from './loader/plugins/loaderPlugin';
+import { AbstractViewerNavbarButton } from './templating/viewerTemplatePlugin';
+import { registerCustomOptimizer } from './optimizer/custom';
 
 /**
  * BabylonJS Viewer
@@ -44,6 +46,6 @@ const Version = viewerGlobals.version;
 console.log("Babylon.js viewer (v" + Version + ")");
 
 // public API for initialization
-export { BABYLON, Version, InitTags, DefaultViewer, AbstractViewer, viewerGlobals, telemetryManager, disableInit, viewerManager, mapperManager, disposeAll, ModelLoader, ViewerModel, AnimationPlayMode, AnimationState, ModelState, ILoaderPlugin };
+export { BABYLON, Version, InitTags, DefaultViewer, AbstractViewer, viewerGlobals, telemetryManager, disableInit, viewerManager, mapperManager, disposeAll, ModelLoader, ViewerModel, AnimationPlayMode, AnimationState, ModelState, ILoaderPlugin, AbstractViewerNavbarButton, registerCustomOptimizer };
 // export publicliy all configuration interfaces
 export * from './configuration';

+ 1 - 1
Viewer/src/labs/texture.ts

@@ -241,7 +241,7 @@ export class TextureUtils {
 
                 let gl = (<any>(scene.getEngine()))._gl;
                 gl.bindTexture(gl.TEXTURE_CUBE_MAP, glTexture);
-                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
+                scene.getEngine()._unpackFlipY(false);
                 if (face instanceof HTMLElement || face instanceof ImageData) {
                     gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level, textureCube.internalFormat, textureCube.internalFormat, textureCube.type, <any>face);
                 } else {

+ 25 - 21
Viewer/src/loader/modelLoader.ts

@@ -1,11 +1,11 @@
-import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, Tools, SceneLoader, Tags } from "babylonjs";
-import { GLTFFileLoader, GLTFLoaderAnimationStartMode } from "babylonjs-loaders";
-import { ViewerConfiguration } from "../configuration/configuration";
-import { IModelConfiguration } from "../configuration/interfaces/modelConfiguration";
-import { ViewerModel, ModelState } from "../model/viewerModel";
-import { getLoaderPluginByName, TelemetryLoaderPlugin, ILoaderPlugin } from './plugins/';
-import { ObservablesManager } from "../managers/observablesManager";
-import { ConfigurationContainer } from "../configuration/configurationContainer";
+import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, SceneLoader, Tags, Tools } from 'babylonjs';
+import { GLTFFileLoader, GLTFLoaderAnimationStartMode } from 'babylonjs-loaders';
+
+import { ConfigurationContainer } from '../configuration/configurationContainer';
+import { IModelConfiguration } from '../configuration/interfaces/modelConfiguration';
+import { ObservablesManager } from '../managers/observablesManager';
+import { ModelState, ViewerModel } from '../model/viewerModel';
+import { getLoaderPluginByName, ILoaderPlugin } from './plugins/';
 
 /**
  * An instance of the class is in charge of loading the model correctly.
@@ -22,6 +22,12 @@ export class ModelLoader {
 
     private _plugins: Array<ILoaderPlugin>;
 
+    private _baseUrl: string;
+
+    public get baseUrl(): string {
+        return this._baseUrl;
+    }
+
     /**
      * Create a new Model loader
      * @param _viewer the viewer using this model loader
@@ -58,26 +64,24 @@ export class ModelLoader {
      */
     public load(modelConfiguration: IModelConfiguration): ViewerModel {
 
-        const model = new ViewerModel(this._observablesManager, modelConfiguration);
+        const model = new ViewerModel(this._observablesManager, modelConfiguration, this._configurationContainer);
 
         model.loadId = this._loadId++;
 
-        if (!modelConfiguration.url) {
-            model.state = ModelState.ERROR;
-            Tools.Error("No URL provided");
-            return model;
-        }
-
-        let base: string;
-
         let filename: any;
         if (modelConfiguration.file) {
-            base = "file:";
+            this._baseUrl = "file:";
             filename = modelConfiguration.file;
         }
-        else {
+        else if (modelConfiguration.url) {
             filename = Tools.GetFilename(modelConfiguration.url) || modelConfiguration.url;
-            base = modelConfiguration.root || Tools.GetFolderPath(modelConfiguration.url);
+            this._baseUrl = modelConfiguration.root || Tools.GetFolderPath(modelConfiguration.url);
+        }
+
+        if (!filename || !this._baseUrl) {
+            model.state = ModelState.ERROR;
+            Tools.Error("No URL provided");
+            return model;
         }
 
 
@@ -85,7 +89,7 @@ export class ModelLoader {
 
         let scene = model.rootMesh.getScene();
 
-        model.loader = SceneLoader.ImportMesh(undefined, base, filename, scene, (meshes, particleSystems, skeletons, animationGroups) => {
+        model.loader = SceneLoader.ImportMesh(undefined, this._baseUrl, filename, scene, (meshes, particleSystems, skeletons, animationGroups) => {
             meshes.forEach(mesh => {
                 Tags.AddTagsTo(mesh, "viewerMesh");
                 model.addMesh(mesh);

+ 4 - 4
Viewer/src/loader/plugins/applyMaterialConfig.ts

@@ -1,7 +1,7 @@
-import { ILoaderPlugin } from "./loaderPlugin";
-import { ViewerModel } from "../../model/viewerModel";
-import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from "babylonjs";
-import { IGLTFLoaderData, GLTF2 } from "babylonjs-loaders";
+import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from 'babylonjs';
+
+import { ViewerModel } from '../../model/viewerModel';
+import { ILoaderPlugin } from './loaderPlugin';
 
 /**
  * Force-apply material configuration right after a material was loaded.

+ 3 - 3
Viewer/src/loader/plugins/extendedMaterialLoaderPlugin.ts

@@ -1,6 +1,6 @@
-import { ILoaderPlugin } from "./loaderPlugin";
-import { ViewerModel } from "../../model/viewerModel";
-import { Color3, Texture, BaseTexture, Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material, PBRMaterial, Engine } from "babylonjs";
+import { Engine, Material, PBRMaterial } from 'babylonjs';
+
+import { ILoaderPlugin } from './loaderPlugin';
 
 /**
  * A (PBR) material will be extended using this function.

+ 5 - 4
Viewer/src/loader/plugins/msftLodLoaderPlugin.ts

@@ -1,7 +1,8 @@
-import { ILoaderPlugin } from "./loaderPlugin";
-import { ViewerModel } from "../../model/viewerModel";
-import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
-import { IGLTFLoaderExtension, GLTF2 } from "babylonjs-loaders";
+import { ISceneLoaderPlugin, ISceneLoaderPluginAsync } from 'babylonjs';
+import { GLTF2, IGLTFLoaderExtension } from 'babylonjs-loaders';
+
+import { ViewerModel } from '../../model/viewerModel';
+import { ILoaderPlugin } from './loaderPlugin';
 
 /**
  * A loder plugin to use MSFT_lod extension correctly (glTF)

+ 9 - 2
Viewer/src/managers/observablesManager.ts

@@ -1,5 +1,6 @@
-import { Observable, Scene, Engine, SceneLoaderProgressEvent, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
-import { ViewerModel } from "../model/viewerModel";
+import { Engine, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Observable, Scene, SceneLoaderProgressEvent } from 'babylonjs';
+
+import { ViewerModel } from '../model/viewerModel';
 
 export class ObservablesManager {
 
@@ -44,6 +45,11 @@ export class ObservablesManager {
     public onViewerInitDoneObservable: Observable<any>;
 
     /**
+     * Will notify when the viewer init started (after configuration was loaded)
+     */
+    public onViewerInitStartedObservable: Observable<any>;
+
+    /**
      * Functions added to this observable will be executed on each frame rendered.
      */
     public onFrameRenderedObservable: Observable<any>;
@@ -57,6 +63,7 @@ export class ObservablesManager {
         this.onModelAddedObservable = new Observable();
         this.onModelRemovedObservable = new Observable();
         this.onViewerInitDoneObservable = new Observable();
+        this.onViewerInitStartedObservable = new Observable();
         this.onLoaderInitObservable = new Observable();
         this.onFrameRenderedObservable = new Observable();
     }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 194 - 67
Viewer/src/managers/sceneManager.ts


+ 4 - 9
Viewer/src/managers/telemetryManager.ts

@@ -43,16 +43,11 @@ export class TelemetryManager {
         let logErrors = true;
 
         while (logErrors) {
-            let gl = (<any>engine)._gl;
-            if (gl && gl.getError) {
-                let error = gl.getError();
-                if (error === gl.NO_ERROR) {
-                    logErrors = false;
-                } else {
-                    this.broadcast("WebGL Error", viewerId, { error: error });
-                }
-            } else {
+            let error = engine.getError();
+            if (error === 0) {
                 logErrors = false;
+            } else {
+                this.broadcast("WebGL Error", viewerId, { error: error });
             }
         }
     }

+ 1 - 1
Viewer/src/model/modelAnimation.ts

@@ -1,4 +1,4 @@
-import { AnimationGroup, Animatable, Skeleton, Vector3 } from "babylonjs";
+import { Animatable, AnimationGroup, Vector3 } from 'babylonjs';
 
 /**
  * Animation play mode enum - is the animation looping or playing once

+ 14 - 8
Viewer/src/model/viewerModel.ts

@@ -1,4 +1,4 @@
-import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, ParticleSystem, Skeleton, IDisposable, Nullable, Animation, Quaternion, Material, Vector3, AnimationPropertiesOverride, QuinticEase, SineEase, CircleEase, BackEase, BounceEase, CubicEase, ElasticEase, ExponentialEase, PowerEase, QuadraticEase, QuarticEase, PBRMaterial, MultiMaterial } from "babylonjs";
+import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, IParticleSystem, Skeleton, IDisposable, Nullable, Animation, Quaternion, Material, Vector3, AnimationPropertiesOverride, QuinticEase, SineEase, CircleEase, BackEase, BounceEase, CubicEase, ElasticEase, ExponentialEase, PowerEase, QuadraticEase, QuarticEase, PBRMaterial, MultiMaterial } from "babylonjs";
 import { GLTFFileLoader, GLTF2 } from "babylonjs-loaders";
 import { IModelConfiguration } from "../configuration/interfaces/modelConfiguration";
 import { IModelAnimationConfiguration } from "../configuration/interfaces/modelAnimationConfiguration";
@@ -48,7 +48,7 @@ export class ViewerModel implements IDisposable {
     /**
      * ParticleSystems connected to this model
      */
-    public particleSystems: Array<ParticleSystem> = [];
+    public particleSystems: Array<IParticleSystem> = [];
     /**
      * Skeletons defined in this model
      */
@@ -114,8 +114,10 @@ export class ViewerModel implements IDisposable {
 
         this.state = ModelState.INIT;
 
-        this.rootMesh = new AbstractMesh("modelRootMesh");
-        this._pivotMesh = new AbstractMesh("pivotMesh");
+        let scene = this._configurationContainer && this._configurationContainer.scene
+
+        this.rootMesh = new AbstractMesh("modelRootMesh", scene);
+        this._pivotMesh = new AbstractMesh("pivotMesh", scene);
         this._pivotMesh.parent = this.rootMesh;
         // rotate 180, gltf fun
         this._pivotMesh.rotation.y += Math.PI;
@@ -241,13 +243,17 @@ export class ViewerModel implements IDisposable {
         // check if this is not a gltf loader and init the animations
         if (this.skeletons.length) {
             this.skeletons.forEach((skeleton, idx) => {
-                let ag = new AnimationGroup("animation-" + idx);
+                let ag = new AnimationGroup("animation-" + idx, this._configurationContainer && this._configurationContainer.scene);
+                let add = false;
                 skeleton.getAnimatables().forEach(a => {
                     if (a.animations[0]) {
                         ag.addTargetedAnimation(a.animations[0], a);
+                        add = true;
                     }
                 });
-                this.addAnimationGroup(ag);
+                if (add) {
+                    this.addAnimationGroup(ag);
+                }
             });
         }
 
@@ -348,7 +354,7 @@ export class ViewerModel implements IDisposable {
      */
     protected _getAnimationByName(name: string): Nullable<IModelAnimation> {
         // can't use .find, noe available on IE
-        let filtered = this._animations.filter(a => a.name === name);
+        let filtered = this._animations.filter(a => a.name === name.trim());
         // what the next line means - if two animations have the same name, they will not be returned!
         if (filtered.length === 1) {
             return filtered[0];
@@ -371,7 +377,7 @@ export class ViewerModel implements IDisposable {
     }
 
     public setCurrentAnimationByName(name: string) {
-        let animation = this._getAnimationByName(name);
+        let animation = this._getAnimationByName(name.trim());
         if (animation) {
             if (this.currentAnimation && this.currentAnimation.state !== AnimationState.STOPPED) {
                 this.currentAnimation.stop();

+ 4 - 0
Viewer/src/optimizer/custom/index.ts

@@ -22,4 +22,8 @@ export function getCustomOptimizerByName(name: string, upgrade?: boolean) {
     }
 
     return cache[name];
+}
+
+export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean) {
+    cache[name] = optimizer;
 }

+ 36 - 0
Viewer/src/templating/plugins/hdButtonPlugin.ts

@@ -0,0 +1,36 @@
+import { AbstractViewerNavbarButton } from "../viewerTemplatePlugin";
+import { DefaultViewer } from "../../viewer/defaultViewer";
+import { EventCallback, Template } from "../templateManager";
+
+export class HDButtonPlugin extends AbstractViewerNavbarButton {
+
+    constructor(private _viewer: DefaultViewer) {
+        super("hd", "hd-button", HDButtonPlugin.HtmlTemplate);
+    }
+
+    onEvent(event: EventCallback): void {
+        let button = event.template.parent.querySelector(".hd-button");
+        if (button) {
+            button.classList.contains("hd-toggled") ? button.classList.remove("hd-toggled") : button.classList.add("hd-toggled");
+        }
+        this._viewer.toggleHD();
+    }
+
+    protected static HtmlTemplate: string = `
+{{#unless hideHd}}
+<style>
+.hd-icon:after {
+    font-size: 16px;
+    content: "\\F765";
+}
+
+.hd-toggled span.hd-icon:after {
+    content: "\\F766";
+}
+</style>
+<button class="hd-button" title="{{text.hdButton}}">
+     <span class="icon hd-icon"></span>
+ </button>
+ {{/unless}}
+`;
+}

+ 62 - 0
Viewer/src/templating/plugins/printButton.ts

@@ -0,0 +1,62 @@
+import { AbstractViewerNavbarButton } from "../viewerTemplatePlugin";
+import { DefaultViewer } from "../../viewer/defaultViewer";
+import { EventCallback } from "../templateManager";
+import { Tools } from "babylonjs";
+
+export class PrintButtonPlugin extends AbstractViewerNavbarButton {
+
+    private _currentModelUrl: string;
+
+    constructor(private _viewer: DefaultViewer) {
+        super("print", "print-button", PrintButtonPlugin.HtmlTemplate);
+
+        this._viewer.onModelLoadedObservable.add((model) => {
+            this._currentModelUrl = "";
+            if (model.configuration.url) {
+                let filename = Tools.GetFilename(model.configuration.url) || model.configuration.url;
+                let baseUrl = model.configuration.root || Tools.GetFolderPath(model.configuration.url);
+
+                //gltf, obj, stl
+                let extension = model.configuration.loader || filename.split(".").pop() || "";
+                let printable = false;
+                // not using .some sue to IE11
+                ["gltf", "glb", "obj", "stl"].forEach(ext => {
+                    if (extension.indexOf(ext) !== -1) {
+                        printable = true;
+                    }
+                })
+                if (printable) {
+                    this._currentModelUrl = baseUrl + filename;
+                }
+            }
+        })
+    }
+
+    onEvent(event: EventCallback): void {
+        if (this._currentModelUrl) {
+            let printUrl = this._currentModelUrl.replace(/https?:\/\//, "com.microsoft.builder3d://");
+            window.open(printUrl, "_self");
+        }
+    }
+
+    protected static HtmlTemplate: string = `
+{{#unless hidePrint}}
+<style>
+
+/* Show only if it's a windows 10 printer  */
+.print-icon.not-win-10 {
+    display: none;
+}
+
+.print-icon:after {
+    font-size: 16px;
+    content: "\\E914";
+}
+
+</style>
+<button class="print-button ${window.navigator.userAgent.indexOf("Windows NT 10.0") === -1 ? "no-win-10" : ""}" title="{{text.printButton}}">
+     <span class="icon print-icon"></span>
+ </button>
+ {{/unless}}
+`;
+}

+ 26 - 6
Viewer/src/templating/templateManager.ts

@@ -80,8 +80,9 @@ export class TemplateManager {
             // register the observers
             //template.onLoaded.add(() => {
             let addToParent = () => {
-                let containingElement = parentTemplate && parentTemplate.parent.querySelector(camelToKebab(name)) || this.containerElement;
-                template.appendTo(containingElement);
+                let lastElements = parentTemplate && parentTemplate.parent.querySelectorAll(camelToKebab(name));
+                let containingElement = (lastElements && lastElements.length && lastElements.item(lastElements.length - 1)) || this.containerElement;
+                template.appendTo(<HTMLElement>containingElement);
                 this._checkLoadedState();
             }
 
@@ -272,6 +273,10 @@ export class Template {
      */
     public onEventTriggered: Observable<EventCallback>;
 
+    public onParamsUpdated: Observable<Template>;
+
+    public onHTMLRendered: Observable<Template>;
+
     /**
      * is the template loaded?
      */
@@ -309,6 +314,8 @@ export class Template {
         this.onAppended = new Observable<Template>();
         this.onStateChange = new Observable<Template>();
         this.onEventTriggered = new Observable<EventCallback>();
+        this.onParamsUpdated = new Observable<Template>();
+        this.onHTMLRendered = new Observable<Template>();
 
         this.loadRequests = [];
 
@@ -373,6 +380,10 @@ export class Template {
         }
     }
 
+    public redraw() {
+        this.updateParams({});
+    }
+
     /**
      * Get the template'S configuration
      */
@@ -432,6 +443,9 @@ export class Template {
         } else {
             this.parent.insertAdjacentHTML("beforeend", this._rawHtml);
         }
+
+        this.onHTMLRendered.notifyObservers(this);
+
         // appended only one frame after.
         setTimeout(() => {
             this._registerEvents();
@@ -530,7 +544,7 @@ export class Template {
     private _getTemplateAsHtml(templateConfig: ITemplateConfiguration): Promise<string> {
         if (!templateConfig) {
             return Promise.reject('No templateConfig provided');
-        } else if (templateConfig.html !== undefined) {
+        } else if (templateConfig.html && !templateConfig.location) {
             return Promise.resolve(templateConfig.html);
         } else {
             let location = this._getTemplateLocation(templateConfig);
@@ -592,10 +606,16 @@ export class Template {
                         // strict null checl is working incorrectly, must override:
                         let event = this._configuration.events[eventName] || {};
                         selectorsArray.filter(selector => event[selector]).forEach(selector => {
-                            if (selector && selector.indexOf('#') !== 0) {
-                                selector = '#' + selector;
-                            }
                             let htmlElement = <HTMLElement>this.parent.querySelector(selector);
+                            if (!htmlElement) {
+                                // backcompat, fallback to id
+                                if (selector && selector.indexOf('#') !== 0) {
+                                    selector = '#' + selector;
+                                }
+                                try {
+                                    htmlElement = <HTMLElement>this.parent.querySelector(selector);
+                                } catch (e) { }
+                            }
                             if (htmlElement) {
                                 let binding = functionToFire.bind(this, selector);
                                 htmlElement.addEventListener(eventName, binding, false);

+ 88 - 0
Viewer/src/templating/viewerTemplatePlugin.ts

@@ -0,0 +1,88 @@
+import { EventCallback, Template } from "./templateManager";
+import * as Handlebars from 'handlebars/dist/handlebars';
+
+export interface IViewerTemplatePlugin {
+
+    readonly templateName: string;
+    readonly eventsToAttach?: Array<string>;
+
+    interactionPredicate(event: EventCallback): boolean;
+    onEvent?(event: EventCallback): void;
+    addHTMLTemplate?(template: Template): void;
+}
+
+export abstract class AbstractViewerNavbarButton implements IViewerTemplatePlugin {
+
+    public readonly templateName: string = "navBar";
+    public readonly eventsToAttach: Array<string> = ['pointerdown'];
+    protected _prepend: boolean = true;
+    protected _buttonName: string;
+    protected _buttonClass: string;
+    protected _htmlTemplate: string;
+
+    constructor(buttonName: string, buttonClass?: string, htmlTemplate?: string) {
+        this._buttonName = buttonName;
+        if (buttonClass) {
+            this._buttonClass = buttonClass;
+        } else {
+            this._buttonClass = buttonName + '-button';
+        }
+        if (htmlTemplate) { this._htmlTemplate = htmlTemplate }
+        else {
+            this._htmlTemplate = `
+<button class="${this._buttonClass}">
+    <span class="icon ${this._buttonName}-icon"></span>
+</button>
+`;
+        }
+    }
+
+    interactionPredicate(event: EventCallback): boolean {
+        let pointerDown = <PointerEvent>event.event;
+        if (pointerDown.button !== 0) return false;
+        var element = (<HTMLElement>event.event.target);
+
+        if (!element) {
+            return false;
+        }
+
+        let elementClasses = element.classList;
+
+        for (let i = 0; i < elementClasses.length; ++i) {
+            let className = elementClasses[i];
+            if (className.indexOf(this._buttonClass) !== -1) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+    abstract onEvent(event: EventCallback): void;
+
+    public addHTMLTemplate(template: Template): void {
+        let element = this._generateHTMLElement(template);
+        let container = template.parent.querySelector("div.default-control");
+        if (container) {
+            if (this._prepend) {
+                container.insertBefore(element, container.firstChild);
+            } else {
+                container.appendChild(element);
+            }
+        }
+    }
+
+    protected _generateHTMLElement(template: Template): Element | DocumentFragment {
+        let compiledTemplate = Handlebars.compile(this._htmlTemplate, { noEscape: (template.configuration.params && !!template.configuration.params.noEscape) });
+        let config = template.configuration.params || {};
+        let rawHtml = compiledTemplate(config);
+        let fragment: Element | DocumentFragment;
+        try {
+            fragment = document.createRange().createContextualFragment(rawHtml);
+        } catch (e) {
+            let test = document.createElement(this._buttonClass);
+            test.innerHTML = rawHtml;
+            fragment = test;
+        }
+        return fragment;
+    }
+}

+ 149 - 51
Viewer/src/viewer/defaultViewer.ts

@@ -1,13 +1,14 @@
 
 
 import { ViewerConfiguration, IModelConfiguration, ILightConfiguration } from './../configuration';
-import { Template, EventCallback, TemplateManager } from '../templating/templateManager';
+import { Template, EventCallback } from '../templating/templateManager';
 import { AbstractViewer } from './viewer';
-import { SpotLight, MirrorTexture, Plane, ShadowGenerator, Texture, BackgroundMaterial, Observable, ShadowLight, CubeTexture, BouncingBehavior, FramingBehavior, Behavior, Light, Engine, Scene, AutoRotationBehavior, AbstractMesh, Quaternion, StandardMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight, FilesInput } from 'babylonjs';
-import { CameraBehavior } from '../interfaces';
+import { SpotLight, Vector3, FilesInput } from 'babylonjs';
 import { ViewerModel } from '../model/viewerModel';
-import { extendClassWithConfig } from '../helper';
 import { IModelAnimation, AnimationState } from '../model/modelAnimation';
+import { IViewerTemplatePlugin } from '../templating/viewerTemplatePlugin';
+import { HDButtonPlugin } from '../templating/plugins/hdButtonPlugin';
+import { PrintButtonPlugin } from '../templating/plugins/printButton';
 
 /**
  * The Default viewer is the default implementation of the AbstractViewer.
@@ -15,7 +16,7 @@ import { IModelAnimation, AnimationState } from '../model/modelAnimation';
  */
 export class DefaultViewer extends AbstractViewer {
 
-
+    public fullscreenElement?: HTMLElement;
 
     /**
      * Create a new default viewer
@@ -32,9 +33,45 @@ export class DefaultViewer extends AbstractViewer {
 
         this.onEngineInitObservable.add(() => {
             this.sceneManager.onLightsConfiguredObservable.add((data) => {
-                this._configureLights(data.newConfiguration, data.model!);
+                this._configureLights();
             })
         });
+
+        this.onInitDoneObservable.add(() => {
+            if (!this.sceneManager.models.length) {
+                this.hideLoadingScreen();
+            }
+        })
+    }
+
+    private _registeredPlugins: Array<IViewerTemplatePlugin> = [];
+
+    public registerTemplatePlugin(plugin: IViewerTemplatePlugin) {
+        //validate
+        if (!plugin.templateName) {
+            throw new Error("No template name provided");
+        }
+        this._registeredPlugins.push(plugin);
+        let template = this.templateManager.getTemplate(plugin.templateName);
+        if (!template) {
+            throw new Error(`Template ${plugin.templateName} not found`);
+        }
+        if (plugin.addHTMLTemplate) {
+            template.onHTMLRendered.add((tmpl) => {
+                plugin.addHTMLTemplate!(tmpl);
+            });
+            template.redraw();
+        }
+
+        if (plugin.eventsToAttach) {
+            plugin.eventsToAttach.forEach(eventName => {
+                plugin.onEvent && this.templateManager.eventManager.registerCallback(plugin.templateName, (event) => {
+                    if (plugin.onEvent && plugin.interactionPredicate(event)) {
+                        plugin.onEvent(event);
+                    }
+                }, eventName);
+            });
+        }
     }
 
     /**
@@ -47,25 +84,31 @@ export class DefaultViewer extends AbstractViewer {
         this._initNavbar();
 
         // close overlay button
-        let closeButton = document.getElementById('close-button');
-        if (closeButton) {
-            closeButton.addEventListener('pointerdown', () => {
-                this.hideOverlayScreen();
-            });
+        let template = this.templateManager.getTemplate('overlay');
+        if (template) {
+
+            let closeButton = template.parent.querySelector('.close-button');
+            if (closeButton) {
+                closeButton.addEventListener('pointerdown', () => {
+                    this.hideOverlayScreen();
+                });
+            }
         }
 
         if (this.configuration.templates && this.configuration.templates.viewer) {
             if (this.configuration.templates.viewer.params && this.configuration.templates.viewer.params.enableDragAndDrop) {
-                let filesInput = new FilesInput(this.engine, this.sceneManager.scene, () => {
-                }, () => {
-                }, () => {
-                }, () => {
-                }, function () {
-                }, (file: File) => {
-                    this.loadModel(file);
-                }, () => {
-                });
-                filesInput.monitorElementForDragNDrop(this.templateManager.getCanvas()!);
+                this.onSceneInitObservable.addOnce(() => {
+                    let filesInput = new FilesInput(this.engine, this.sceneManager.scene, () => {
+                    }, () => {
+                    }, () => {
+                    }, () => {
+                    }, function () {
+                    }, (file: File) => {
+                        this.loadModel(file);
+                    }, () => {
+                    });
+                    filesInput.monitorElementForDragNDrop(this.templateManager.getCanvas()!);
+                })
             }
         }
 
@@ -73,10 +116,6 @@ export class DefaultViewer extends AbstractViewer {
         return super._onTemplatesLoaded();
     }
 
-    private _dropped(evt: EventCallback) {
-
-    }
-
     private _initNavbar() {
         let navbar = this.templateManager.getTemplate('navBar');
         if (navbar) {
@@ -85,7 +124,7 @@ export class DefaultViewer extends AbstractViewer {
             // an example how to trigger the help button. publiclly available
             this.templateManager.eventManager.registerCallback("navBar", () => {
                 // do your thing
-            }, "pointerdown", "#help-button");
+            }, "pointerdown", ".help-button");
 
             this.templateManager.eventManager.registerCallback("navBar", (event: EventCallback) => {
                 const evt = event.event;
@@ -96,12 +135,21 @@ export class DefaultViewer extends AbstractViewer {
                 this._currentAnimation.goToFrame(gotoFrame);
             }, "input");
 
-            this.templateManager.eventManager.registerCallback("navBar", (e) => {
+            this.templateManager.eventManager.registerCallback("navBar", () => {
                 if (this._resumePlay) {
                     this._togglePlayPause(true);
                 }
                 this._resumePlay = false;
-            }, "pointerup", "#progress-wrapper");
+            }, "pointerup", ".progress-wrapper");
+
+            if (window.devicePixelRatio === 1 && navbar.configuration.params && !navbar.configuration.params.hideHdButton) {
+                navbar.updateParams({
+                    hideHdButton: true
+                });
+            }
+
+            this.registerTemplatePlugin(new HDButtonPlugin(this));
+            this.registerTemplatePlugin(new PrintButtonPlugin(this));
         }
     }
 
@@ -122,7 +170,19 @@ export class DefaultViewer extends AbstractViewer {
 
         let parentClasses = element.parentElement!.classList;
 
-        switch (element.id) {
+        let elementClasses = element.classList;
+
+        let elementName = "";
+
+        for (let i = 0; i < elementClasses.length; ++i) {
+            let className = elementClasses[i];
+            if (className.indexOf("-button") !== -1 || className.indexOf("-wrapper") !== -1) {
+                elementName = className;
+                break;
+            }
+        }
+
+        switch (elementName) {
             case "speed-button":
             case "types-button":
                 if (parentClasses.contains("open")) {
@@ -135,9 +195,10 @@ export class DefaultViewer extends AbstractViewer {
                 this._togglePlayPause();
                 break;
             case "label-option-button":
-                var label = element.dataset["value"];
-                if (label) {
-                    this._updateAnimationType(label);
+                var value = element.dataset["value"];
+                var label = element.querySelector("span.animation-label");
+                if (label && value) {
+                    this._updateAnimationType({ value: value.trim(), label: label.innerHTML });
                 }
                 break;
             case "speed-option-button":
@@ -157,6 +218,9 @@ export class DefaultViewer extends AbstractViewer {
             case "fullscreen-button":
                 this.toggleFullscreen();
                 break;
+            case "vr-button":
+                this.toggleVR();
+                break;
             default:
                 return;
         }
@@ -195,7 +259,7 @@ export class DefaultViewer extends AbstractViewer {
     private _updateProgressBar = () => {
         let navbar = this.templateManager.getTemplate('navBar');
         if (!navbar) return;
-        var progressSlider = <HTMLInputElement>navbar.parent.querySelector("input#progress-wrapper");
+        var progressSlider = <HTMLInputElement>navbar.parent.querySelector("input.progress-wrapper");
         if (progressSlider && this._currentAnimation) {
             const progress = this._currentAnimation.currentFrame / this._currentAnimation.frames * 100;
             var currentValue = progressSlider.valueAsNumber;
@@ -243,42 +307,76 @@ export class DefaultViewer extends AbstractViewer {
     /** 
      * Update Current Animation Type
      */
-    private _updateAnimationType = (label: string, paramsObject?: any) => {
+    private _updateAnimationType = (data: { label: string, value: string }, paramsObject?: any) => {
         let navbar = this.templateManager.getTemplate('navBar');
         if (!navbar) return;
 
-        if (label) {
-            this._currentAnimation = this.sceneManager.models[0].setCurrentAnimationByName(label);
+        if (data) {
+            this._currentAnimation = this.sceneManager.models[0].setCurrentAnimationByName(data.value);
         }
 
         if (paramsObject) {
-            paramsObject.selectedAnimation = (this._animationList.indexOf(label) + 1);
-            paramsObject.selectedAnimationName = label;
+            paramsObject.selectedAnimation = (this._animationList.indexOf(data.value) + 1);
+            paramsObject.selectedAnimationName = data.label;
         } else {
             navbar.updateParams({
-                selectedAnimation: (this._animationList.indexOf(label) + 1),
-                selectedAnimationName: label
+                selectedAnimation: (this._animationList.indexOf(data.value) + 1),
+                selectedAnimationName: data.label
             });
         }
 
         this._updateAnimationSpeed("1.0", paramsObject);
     }
 
+    protected _initVR() {
+        this.engine.onVRDisplayChangedObservable.add(() => {
+            let viewerTemplate = this.templateManager.getTemplate('viewer');
+            let viewerElement = viewerTemplate && viewerTemplate.parent;
+
+            if (viewerElement) {
+                if (this.sceneManager.vrHelper!.isInVRMode) {
+                    viewerElement.classList.add("in-vr");
+                } else {
+                    viewerElement.classList.remove("in-vr");
+                }
+            }
+        });
+        if (this.sceneManager.vrHelper) {
+            // due to the way the experience helper is exisintg VR, this must be added.
+            this.sceneManager.vrHelper.onExitingVR.add(() => {
+                let viewerTemplate = this.templateManager.getTemplate('viewer');
+                let viewerElement = viewerTemplate && viewerTemplate.parent;
+
+                if (viewerElement) {
+                    viewerElement.classList.remove("in-vr");
+                }
+            });
+        }
+        super._initVR();
+    }
+
     /**
      * Toggle fullscreen of the entire viewer
      */
     public toggleFullscreen = () => {
         let viewerTemplate = this.templateManager.getTemplate('viewer');
         let viewerElement = viewerTemplate && viewerTemplate.parent;
-
-        if (viewerElement) {
-            let fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || (<any>document).mozFullScreenElement || (<any>document).msFullscreenElement;
-            if (!fullscreenElement) {
-                let requestFullScreen = viewerElement.requestFullscreen || viewerElement.webkitRequestFullscreen || (<any>viewerElement).msRequestFullscreen || (<any>viewerElement).mozRequestFullScreen;
-                requestFullScreen.call(viewerElement);
+        let fullscreenElement = this.fullscreenElement || viewerElement;
+
+        if (fullscreenElement) {
+            let currentElement = document.fullscreenElement || document.webkitFullscreenElement || (<any>document).mozFullScreenElement || (<any>document).msFullscreenElement;
+            if (!currentElement) {
+                let requestFullScreen = fullscreenElement.requestFullscreen || fullscreenElement.webkitRequestFullscreen || (<any>fullscreenElement).msRequestFullscreen || (<any>fullscreenElement).mozRequestFullScreen;
+                requestFullScreen.call(fullscreenElement);
+                if (viewerElement) {
+                    viewerElement.classList.add("in-fullscreen");
+                }
             } else {
                 let exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || (<any>document).msExitFullscreen || (<any>document).mozCancelFullScreen
                 exitFullscreen.call(document);
+                if (viewerElement) {
+                    viewerElement.classList.remove("in-fullscreen");
+                }
             }
         }
     }
@@ -308,7 +406,7 @@ export class DefaultViewer extends AbstractViewer {
         } else {
 
             let animationNames = model.getAnimationNames();
-            newParams.animations = animationNames;
+            newParams.animations = animationNames.map(a => { return { label: a, value: a } });
             if (animationNames.length) {
                 this._isAnimationPaused = (model.configuration.animation && !model.configuration.animation.autoStart) || !model.configuration.animation;
                 this._animationList = animationNames;
@@ -320,7 +418,7 @@ export class DefaultViewer extends AbstractViewer {
                         animationIndex = 0;
                     }
                 }
-                this._updateAnimationType(animationNames[animationIndex], newParams);
+                this._updateAnimationType(newParams.animations[animationIndex], newParams);
             } else {
                 newParams.animations = null;
             }
@@ -498,6 +596,7 @@ export class DefaultViewer extends AbstractViewer {
     }
 
     protected _onConfigurationLoaded(configuration: ViewerConfiguration) {
+
         super._onConfigurationLoaded(configuration);
 
         // initialize the templates
@@ -519,10 +618,9 @@ export class DefaultViewer extends AbstractViewer {
      * @param lightsConfiguration the light configuration to use
      * @param model the model that will be used to configure the lights (if the lights are model-dependant)
      */
-    private _configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean | number } = {}, model?: ViewerModel) {
+    private _configureLights() {
         // labs feature - flashlight
         if (this.configuration.lab && this.configuration.lab.flashlight) {
-            let pointerPosition = Vector3.Zero();
             let lightTarget;
             let angle = 0.5;
             let exponent = Math.PI / 2;
@@ -547,7 +645,7 @@ export class DefaultViewer extends AbstractViewer {
 
             }
             this.sceneManager.scene.constantlyUpdateMeshUnderPointer = true;
-            this.sceneManager.scene.onPointerObservable.add((eventData, eventState) => {
+            this.sceneManager.scene.onPointerObservable.add((eventData) => {
                 if (eventData.type === 4 && eventData.pickInfo) {
                     lightTarget = (eventData.pickInfo.pickedPoint);
                 } else {

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 175 - 36
Viewer/src/viewer/viewer.ts


+ 3 - 0
Viewer/tests/commons/helper.ts

@@ -8,6 +8,9 @@ export const useNullEngine = true;
 export class Helper {
 
     public static getNewViewerInstance(element: HTMLElement = Helper.getViewerContainer(), configuration?: ViewerConfiguration, useAbstractViewer?: boolean) {
+        if (configuration) {
+            configuration.extends = configuration.extends || "default";
+        }
         if (useNullEngine) {
             if (useAbstractViewer) {
                 return new NullEngineAbstractViewer(element, configuration);

+ 5 - 9
Viewer/tests/unit/src/configuration/updateConfiguration.ts

@@ -36,7 +36,7 @@ describe(name + " scene", () => {
             }
         })
         viewer.onInitDoneObservable.add(() => {
-            assert.isUndefined(viewer.configuration.scene);
+            // assert.isUndefined(viewer.configuration.scene);
             assert.equal(showCalled, 0);
             assert.equal(hideCalled, 0);
             viewer.updateConfiguration({
@@ -155,19 +155,15 @@ describe(name + " scene", () => {
             assert.equal(viewer.sceneManager.reflectionColor.b, 1);
 
             viewer.updateConfiguration({
-                scene: {
+                environmentMap: {
+                    tintLevel: 1,
+                    texture: "",
+                    rotationY: 0,
                     mainColor: {
                         r: 0.5,
                         g: 0.5,
                         b: 0.5
                     }
-                },
-                lab: {
-                    environmentMap: {
-                        tintLevel: 1,
-                        texture: "",
-                        rotationY: 0
-                    }
                 }
             });
 

+ 14 - 2
Viewer/tests/unit/src/viewer/sceneManager.ts

@@ -146,6 +146,12 @@ describe(name, function () {
         });
 
         viewer.onInitDoneObservable.add(() => {
+            if (!viewer.sceneManager.environmentHelper) {
+                assert.fail();
+                viewer.dispose();
+                done();
+                return;
+            }
             // ground should be defined, and mirror should be enabled
             assert.isDefined(viewer.sceneManager.environmentHelper.ground);
 
@@ -177,6 +183,12 @@ describe(name, function () {
         });
 
         viewer.onInitDoneObservable.add(() => {
+            if (!viewer.sceneManager.environmentHelper) {
+                assert.fail();
+                viewer.dispose();
+                done();
+                return;
+            }
             // ground should be defined, and mirror should be enabled
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial);
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
@@ -184,7 +196,7 @@ describe(name, function () {
             viewer.sceneManager.groundMirrorEnabled = false;
 
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial);
-            assert.isNull(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
+            assert.isNotOk(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
 
             viewer.sceneManager.groundMirrorEnabled = true;
 
@@ -198,7 +210,7 @@ describe(name, function () {
             });
 
             assert.isDefined(viewer.sceneManager.environmentHelper.groundMaterial);
-            assert.isNull(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
+            assert.isNotOk(viewer.sceneManager.environmentHelper.groundMaterial!.reflectionTexture);
             assert.isTrue(viewer.sceneManager.groundMirrorEnabled);
 
             viewer.dispose();

+ 2 - 1
Viewer/tests/unit/tsconfig.json

@@ -20,7 +20,7 @@
         "skipDefaultLibCheck": true,
         "skipLibCheck": true,
         "baseUrl": "./src/",
-        "rootDir": "./",
+        "rootDir": "../../",
         "paths": {
             "babylonjs": [
                 "../../../../dist/preview release/babylon.d.ts"
@@ -35,6 +35,7 @@
                 "../../src/assets/"
             ]
         },
+        "outDir": "./build"
     },
     "include": [
         "./src/**/*.ts"

+ 4 - 2
Viewer/tests/unit/webpack.config.js

@@ -1,6 +1,7 @@
 const path = require('path');
 
 module.exports = {
+    context: __dirname,
     entry: {
         'test': __dirname + '/src/index.ts'
     },
@@ -24,9 +25,10 @@ module.exports = {
         oimo: 'OIMO',
         "earcut": true
     },
+    mode: "development",
     devtool: 'source-map',
     module: {
-        loaders: [{
+        rules: [{
             test: /\.tsx?$/,
             loader: 'ts-loader',
             exclude: /node_modules/
@@ -46,7 +48,7 @@ module.exports = {
         },
         {
             test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
-            loader: 'base64-font-loader'
+            loader: 'base64-inline-loader?limit=1000&name=[name].[ext]'
         }]
     },
     devServer: {

BIN=BIN
Viewer/tests/validation/ReferenceImages/Control.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/ControlDefault.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/Diffuse.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/Emissive.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv0-0.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv0-100.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv0-50.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv100-0.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv100-100.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv100-50.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv50-0.png


BIN=BIN
Viewer/tests/validation/ReferenceImages/MainColorEnv50-100.png


+ 0 - 0
Viewer/tests/validation/ReferenceImages/MainColorEnv50-50.png


Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio