Browse Source

Merge branch 'master' into guiRectFix

Trevor Baron 6 năm trước cách đây
mục cha
commit
c3221ba5bb
100 tập tin đã thay đổi với 313044 bổ sung237197 xóa
  1. 6 2
      .gitignore
  2. 6 6
      .travis.yml
  3. 16 5
      .vscode/settings.json
  4. 2 9
      .vscode/tasks.json
  5. 60788 57152
      Playground/babylon.d.txt
  6. 1 1
      Playground/index-local.html
  7. 3 3
      Playground/index.html
  8. 2 2
      Playground/ts.html
  9. 117 0
      Tools/Config/config.js
  10. 686 0
      Tools/Config/config.json
  11. 57 91
      Tools/DevLoader/BabylonLoader.js
  12. 0 2132
      Tools/Gulp/config.json
  13. 0 58
      Tools/Gulp/gulp-addDtsExport.js
  14. 0 89
      Tools/Gulp/gulp-addES6Exports.js
  15. 0 113
      Tools/Gulp/gulp-addModuleExports.js
  16. 0 99
      Tools/Gulp/gulp-appendSrcToVariable.js
  17. 0 133
      Tools/Gulp/gulp-babylonModule.js
  18. 0 80
      Tools/Gulp/gulp-calculateDependencies.js
  19. 0 37
      Tools/Gulp/gulp-decorateAndExtends.js
  20. 0 96
      Tools/Gulp/gulp-dtsModuleSupport.js
  21. 0 214
      Tools/Gulp/gulp-es6ModuleExports.js
  22. 0 97
      Tools/Gulp/gulp-removeShaderComments.js
  23. 0 747
      Tools/Gulp/gulp-validateTypedoc.js
  24. 53 1481
      Tools/Gulp/gulpfile.js
  25. 113 0
      Tools/Gulp/helpers/gulp-addModuleExports.js
  26. 139 0
      Tools/Gulp/helpers/gulp-processAmdDeclarationToModule.js
  27. 42 0
      Tools/Gulp/helpers/gulp-processImportsToEs6.js
  28. 44 0
      Tools/Gulp/helpers/gulp-processLooseDeclarationsEs6.js
  29. 262 0
      Tools/Gulp/helpers/gulp-processModuleDeclarationToNamespace.js
  30. 137 0
      Tools/Gulp/helpers/gulp-processShaders.js
  31. 100 0
      Tools/Gulp/helpers/gulp-remapPaths.js
  32. 97 0
      Tools/Gulp/helpers/gulp-removeShaderComments.js
  33. 163 0
      Tools/Gulp/helpers/gulp-validateImports.js
  34. 684 0
      Tools/Gulp/helpers/gulp-validateTypedoc.js
  35. 2 46
      Tools/Gulp/package.json
  36. 0 72
      Tools/Gulp/processViewerDeclaration.js
  37. 2 2
      Tools/Gulp/profiling.html
  38. 9 49
      Tools/Gulp/readme.md
  39. 75 0
      Tools/Gulp/tasks/gulpTasks-dependencies.js
  40. 64 0
      Tools/Gulp/tasks/gulpTasks-importLint.js
  41. 21 0
      Tools/Gulp/tasks/gulpTasks-intellisense.js
  42. 184 0
      Tools/Gulp/tasks/gulpTasks-libraries.js
  43. 296 0
      Tools/Gulp/tasks/gulpTasks-librariesES6.js
  44. 48 0
      Tools/Gulp/tasks/gulpTasks-localRun.js
  45. 16 0
      Tools/Gulp/tasks/gulpTasks-netlify.js
  46. 33 0
      Tools/Gulp/tasks/gulpTasks-npmPackages.js
  47. 22 0
      Tools/Gulp/tasks/gulpTasks-remapPaths.js
  48. 324 0
      Tools/Gulp/tasks/gulpTasks-tests.js
  49. 52 0
      Tools/Gulp/tasks/gulpTasks-tsLint.js
  50. 61 0
      Tools/Gulp/tasks/gulpTasks-typedoc.js
  51. 118 0
      Tools/Gulp/tasks/gulpTasks-viewerLibraries.js
  52. 87 0
      Tools/Gulp/tasks/gulpTasks-watchCore.js
  53. 83 0
      Tools/Gulp/tasks/gulpTasks-watchLibraries.js
  54. 50 0
      Tools/Gulp/tasks/gulpTasks-whatsNew.js
  55. 109 0
      Tools/NodeHelpers/colorConsole.js
  56. 26 0
      Tools/NodeHelpers/rmDir.js
  57. 21 0
      Tools/Publisher/helpers/getFiles.js
  58. 34 0
      Tools/Publisher/helpers/publish.js
  59. 18 281
      Tools/Publisher/index.js
  60. 0 20
      Tools/Publisher/package.json
  61. 15 0
      Tools/Publisher/production.js
  62. 20 0
      Tools/Publisher/tasks/buildBabylonJSAndDependencies.js
  63. 78 0
      Tools/Publisher/tasks/main.js
  64. 41 0
      Tools/Publisher/tasks/prepareAdditionalDevPackages.js
  65. 61 0
      Tools/Publisher/tasks/prepareEs6DevPackages.js
  66. 61 0
      Tools/Publisher/tasks/prepareUMDDevPackages.js
  67. 31 0
      Tools/Publisher/tasks/processAdditionalPackages.js
  68. 109 0
      Tools/Publisher/tasks/processEs6Packages.js
  69. 120 0
      Tools/Publisher/tasks/processUMDPackages.js
  70. 58 0
      Tools/Publisher/tasks/processUMDViewer.js
  71. 57 0
      Tools/Publisher/tasks/versionNumberManager.js
  72. 74 0
      Tools/WebpackPlugins/babylonExternals.js
  73. 66 0
      Tools/WebpackPlugins/babylonWebpackConfig.js
  74. 0 139
      Tools/WebpackShaderLoader/index.js
  75. 1 1
      Viewer/assets/readme.md
  76. 0 1
      Viewer/package.json
  77. 0 6
      Viewer/src/externalModules.d.ts
  78. 2 2
      Viewer/src/loader/plugins/msftLodLoaderPlugin.ts
  79. 5 5
      Viewer/src/loader/plugins/telemetryLoaderPlugin.ts
  80. 28 28
      Viewer/src/managers/sceneManager.ts
  81. 4 3
      Viewer/src/model/viewerModel.ts
  82. 1 1
      Viewer/src/viewer/viewer.ts
  83. 0 17
      Viewer/tests/package.json
  84. 6 11
      Viewer/tests/unit/src/configuration/updateConfiguration.ts
  85. 2 1
      Viewer/tests/unit/src/viewer/sceneManager.ts
  86. 2 1
      Viewer/tests/unit/src/viewer/viewer.ts
  87. 3 3
      Viewer/tests/unit/src/viewerReference.ts
  88. 2 2
      Viewer/tests/unit/tsconfig.json
  89. 0 6
      Viewer/tests/unit/webpack.config.js
  90. 4 2
      Viewer/tests/validation/validation.js
  91. 3 8
      Viewer/tsconfig-gulp.json
  92. 3 3
      Viewer/tsconfig.json
  93. 0 6
      Viewer/webpack.config.js
  94. 0 5
      Viewer/webpack.gulp.config.js
  95. 53120 51510
      dist/preview release/babylon.d.ts
  96. 16 1
      dist/preview release/babylon.js
  97. 137943 122318
      dist/preview release/babylon.max.js
  98. 1 0
      dist/preview release/babylon.max.js.map
  99. 55834 0
      dist/preview release/babylon.module.d.ts
  100. 0 0
      dist/preview release/babylon.no-module.max.js

+ 6 - 2
.gitignore

@@ -1,6 +1,5 @@
 # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
 [Bb]in/
-[Oo]bj/
 
 # mstest test results
 TestResults
@@ -17,7 +16,9 @@ TestResults
 
 # javascript files
 src/**/*.js
+!src/webpack.config.js
 src/**/*.d.ts
+!src/LibDeclarations/*.d.ts
 loaders/src/**/*.js
 materialsLibrary/src/**/*.js
 proceduralTexturesLibrary/src/**/*.js
@@ -107,7 +108,6 @@ AppPackages/
 
 # Others
 [Bb]in
-[Oo]bj
 sql
 TestResults
 [Tt]est[Rr]esult*
@@ -164,6 +164,10 @@ node_modules
 !dist/**/*.d.ts
 !dist/**/*.js.map
 !lib.d.ts
+!src/LibDeclarations/*.d.ts
+*.fragment.ts
+*.vertex.ts
+**/ShadersInclude/**/*.ts
 
 # Split declaration file
 !ISplit.d.ts

+ 6 - 6
.travis.yml

@@ -4,14 +4,14 @@ language: node_js
 node_js:
 - '8'
 git:
-  depth: 3
+  depth: 2
 cache:
   directories:
-  - Tools/Gulp/node_modules
+  - node_modules
   - Playground/node_modules
-  - tests/unit/node_modules
 install:
-- travis_retry npm install -g gulp
+- travis_retry npm install -g gulp@4.0.0
+- travis_retry npm install -g typescript
 - cd ./Tools/Gulp
 - travis_retry npm install
 jobs:
@@ -21,8 +21,8 @@ jobs:
     script: gulp tests-whatsnew
   - env: JOB=DocumentationCheck
     script: gulp typedoc-check
-  - env: JOB=Styling
-    script: gulp tsLint
+  - env: JOB=Linting
+    script: gulp fullLint
   - env: JOB=Build
     script: gulp typescript-all
   - env: JOB=Tests

+ 16 - 5
.vscode/settings.json

@@ -11,7 +11,6 @@
         "**/node_modules": true,
         "**/temp": true,
         "**/.temp": true,
-        "src/**/*.d.ts": true,
         "gui/**/*.d.ts": true,
         "inspector/**/*.d.ts": true,
         "loaders/**/*.d.ts": true,
@@ -20,11 +19,20 @@
         "proceduralTexturesLibrary/**/*.d.ts": true,
         "serielazers/**/*.d.ts": true,
         "Viewer/**/*.d.ts": true,
-        "**/*.js.map": true,
+        "gui/**/*.js.map": true,
+        "inspector/**/*.js.map": true,
+        "loaders/**/*.js.map": true,
+        "materialsLibrary/**/*.js.map": true,
+        "postProcessesLibrary/**/*.js.map": true,
+        "proceduralTexturesLibrary/**/*.js.map": true,
+        "serielazers/**/*.js.map": true,
         "**/*.js.fx": true,
         "**/*.js": {
             "when": "$(basename).ts"
-        }
+        },
+        "**/*.fragment.ts": true,
+        "**/*.vertex.ts": true,
+        "**/ShadersInclude/**/*.ts": true
     },
     "files.associations": {
         "*.fx": "glsl"
@@ -40,9 +48,12 @@
         "**/*.js": {
             "when": "$(basename).ts"
         },
-        "**/*.d.ts": true,
+        "dist/**/*.d.ts": true,
+        "**/*.fragment.ts": true,
+        "**/*.vertex.ts": true,
+        "**/ShadersInclude/**/*.ts": true,
         "assets": true
     },
     "editor.tabSize": 4,
-    "typescript.tsdk": "./Tools/Gulp/node_modules/typescript/lib"
+    "typescript.tsdk": "node_modules\\typescript\\lib"
 }

+ 2 - 9
.vscode/tasks.json

@@ -35,19 +35,12 @@
                 },
                 "background": {
                     "activeOnStart": true,
-                    "beginsPattern": "Starting \\'watch\\'",
-                    "endsPattern": "Entrypoint babylonjs-inspector"
+                    "beginsPattern": "Starting \\'watchCore\\'",
+                    "endsPattern": "Watching for file changes"
                 }
             }
         },
         {
-            "taskName": "typescript-all",
-            "isBuildCommand": true,
-            "problemMatcher": [
-                "$tsc"
-            ]
-        },
-        {
             "label": "serve-viewer",
             "type": "npm",
             "script": "start:server",

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 60788 - 57152
Playground/babylon.d.txt


+ 1 - 1
Playground/index-local.html

@@ -23,7 +23,7 @@
     <!-- Monaco -->
 
     <!-- Babylon.js -->
-    <script src="../tools/DevLoader/BabylonLoader.js"></script>
+    <script src="../Tools/DevLoader/BabylonLoader.js"></script>
 
     <link href="css/index.css" rel="stylesheet" />
 </head>

+ 3 - 3
Playground/index.html

@@ -46,7 +46,7 @@
     <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/loaders/babylonjs.loaders.min.js"></script>
     <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
 
     <!-- Monaco -->
@@ -56,8 +56,8 @@
     <!-- 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 async src="https://www.babylontoolkit.com/playground/scripts/babylon.navmesh.js"></script>
-    <script async src="https://www.babylontoolkit.com/playground/scripts/babylon.manager.js"></script> -->
+    <!-- <script async src="https://www.babylontoolkit.com/Playground/scripts/babylon.navmesh.js"></script>
+    <script async src="https://www.babylontoolkit.com/Playground/scripts/babylon.manager.js"></script> -->
 
     <link href="css/index.css" rel="stylesheet" />
 </head>

+ 2 - 2
Playground/ts.html

@@ -54,8 +54,8 @@
         <!-- 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://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" />

+ 117 - 0
Tools/Config/config.js

@@ -0,0 +1,117 @@
+const path = require("path");
+const fs = require("fs-extra");
+
+const config = require("./config.json");
+const configFolder = __dirname;
+
+const rootFolder = path.resolve(configFolder, "../../");
+const tempFolder = path.resolve(rootFolder, config.build.tempDirectory);
+const outputFolder = path.resolve(configFolder, config.build.outputDirectory);
+const localDevES6Folder = path.join(tempFolder, config.build.localDevES6FolderName);
+const localDevUMDFolder = path.join(tempFolder, config.build.localDevUMDFolderName);
+const packageUMDFolder = path.join(tempFolder, config.build.packageUMDFolderName);
+const packageUMDDevFolder = path.join(tempFolder, config.build.packageUMDDevFolderName);
+const sourceES6Folder = path.join(tempFolder, config.build.sourceES6FolderName);
+const distES6Folder = path.join(tempFolder, config.build.distES6FolderName);
+const packageES6Folder = path.join(tempFolder, config.build.packageES6FolderName);
+const packageES6DevFolder = path.join(tempFolder, config.build.packageES6DevFolderName);
+
+const tempTypingsAMDFileName = config.build.tempTypingsAMDFileName;
+const tempTypingsFileName = tempTypingsAMDFileName.replace(".js", ".d.ts");
+const tempTypingsAMDFilePath = path.join(tempFolder, tempTypingsAMDFileName);
+const tempTypingsFilePath = path.join(tempFolder, tempTypingsFileName);
+
+config.computed = {
+    rootFolder,
+    tempFolder,
+    outputFolder,
+    localDevES6Folder,
+    localDevUMDFolder,
+    packageUMDFolder,
+    packageUMDDevFolder,
+    sourceES6Folder,
+    distES6Folder,
+    packageES6Folder,
+    packageES6DevFolder,
+    tempTypingsAMDFileName,
+    tempTypingsFileName,
+    tempTypingsAMDFilePath,
+    tempTypingsFilePath
+}
+
+config.additionalNpmPackages.forEach(package => {
+    let packagePath = path.join(rootFolder, package.path);
+    let packageDevDirectory = path.join(localDevUMDFolder, package.name);
+
+    package.computed = {
+        path: packagePath,
+        packageDevDirectory
+    };
+});
+
+config.modules.map(function(module) {
+    const settings = config[module];
+
+    const mainDirectory = path.resolve(rootFolder, settings.build.mainFolder);
+    const distFolder = (settings.build.distOutputDirectory !== undefined) ? settings.build.distOutputDirectory : module;
+    const distDirectory = path.join(outputFolder, distFolder);
+    const localDevES6Directory = path.join(localDevES6Folder, module);
+    const localDevUMDDirectory = path.join(localDevUMDFolder, distFolder);
+    const packageUMDDirectory = path.join(packageUMDFolder, module);
+    const packageUMDDevDirectory = path.join(packageUMDDevFolder, module);
+    const sourceES6Directory = path.join(sourceES6Folder, module);
+    const distES6Directory = path.join(distES6Folder, module);
+    const packageES6Directory = path.join(packageES6Folder, module);
+    const packageES6DevDirectory = path.join(packageES6DevFolder, module);
+
+    const webpackConfigPath = path.join(mainDirectory, "webpack.config.js");
+    const tsConfigPath = path.join(mainDirectory, "tsconfig.json");
+    const packageJSONPath = settings.build.packageJSON ? 
+        path.join(rootFolder, settings.build.packageJSON) : 
+        path.join(distDirectory, 'package.json');
+
+    settings.computed = {
+        mainDirectory,
+        distDirectory,
+        localDevES6Directory,
+        localDevUMDDirectory,
+        packageUMDDirectory,
+        packageUMDDevDirectory,
+        sourceES6Directory,
+        distES6Directory,
+        packageES6Directory,
+        packageES6DevDirectory,
+        webpackConfigPath,
+        tsConfigPath,
+        packageJSONPath
+    }
+
+    // Prevent es6 bundled lib crash.
+    if (fs.existsSync(tsConfigPath)) {
+        const tsConfig = require(tsConfigPath);
+        const srcDirectory = path.resolve(mainDirectory, tsConfig.compilerOptions.rootDir);
+
+        const shaderGlob = srcDirectory.replace(/\\/g, "/") + "/**/*.fx";
+        const shaderTSGlob = [
+            srcDirectory.replace(/\\/g, "/") + "/**/*.fragment.ts",
+            srcDirectory.replace(/\\/g, "/") + "/**/*.vertex.ts",
+            srcDirectory.replace(/\\/g, "/") + "/**/ShadersInclude/*.ts",
+        ];
+        const tsGlob = srcDirectory.replace(/\\/g, "/") + "/**/*.ts*";
+
+        for (let library of settings.libraries) {
+            const entryPath = path.join(srcDirectory, library.entry);
+
+            library.computed = {
+                entryPath
+            };
+        }
+
+        settings.computed.srcDirectory = srcDirectory;
+        settings.computed.shaderGlob = shaderGlob;
+        settings.computed.shaderTSGlob = shaderTSGlob;
+        settings.computed.tsGlob = tsGlob;
+    }
+});
+
+module.exports = config;

+ 686 - 0
Tools/Config/config.json

@@ -0,0 +1,686 @@
+{
+    "build": {
+        "outputDirectory": "../../dist/preview release",
+        "tempDirectory": "./.temp/",
+        "tempTypingsAMDFileName": "tempTypings.js",
+        "localDevES6FolderName": "localDevES6",
+        "localDevUMDFolderName": "localDevUMD",
+        "packageUMDFolderName": "packageUMD",
+        "packageUMDDevFolderName": "packageUMDDev",
+        "sourceES6FolderName": "sourceES6",
+        "distES6FolderName": "distES6",
+        "packageES6FolderName": "packageES6",
+        "packageES6DevFolderName": "packageES6Dev",
+        "playgroundDirectory": "../../Playground/",
+        "intellisenseFile": "babylon.d.txt",
+        "intellisenseSources": [
+            "../../dist/preview release/babylon.d.ts",
+            "../../dist/preview release/gui/babylon.gui.d.ts",
+            "../../dist/preview release/loaders/babylonjs.loaders.d.ts",
+            "../../dist/preview release/serializers/babylonjs.serializers.d.ts",
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts",
+            "../../dist/preview release/materialsLibrary/babylonjs.materials.d.ts",
+            "../../dist/preview release/postProcessesLibrary/babylonjs.postProcess.d.ts",
+            "../../dist/preview release/proceduralTexturesLibrary/babylonjs.proceduralTextures.d.ts"
+        ],
+        "typedocGenerationFiles": [
+            "../../dist/preview release/babylon.d.ts",
+            "../../dist/preview release/gui/babylon.gui.d.ts",
+            "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts",
+            "../../dist/preview release/loaders/babylonjs.loaders.d.ts",
+            "../../dist/preview release/serializers/babylonjs.serializers.d.ts"
+        ],
+        "typedocEntryPoint": ["\"babylon.d\"", "BABYLON"],
+        "typedocJSON": "../../.temp/babylon.typedoc.json",
+        "typedocValidationBaseline": "../../dist/preview release/typedocValidationBaseline.json"
+    },
+    "modules": [
+        "core",
+        "materialsLibrary",
+        "postProcessesLibrary",
+        "proceduralTexturesLibrary",
+        "loaders",
+        "serializers",
+        "gui",
+        "inspector"
+    ],
+    "lintModules": [
+        "core",
+        "materialsLibrary",
+        "postProcessesLibrary",
+        "proceduralTexturesLibrary",
+        "loaders",
+        "serializers",
+        "gui"
+    ],
+    "viewerModules": [
+        "viewer",
+        "viewer-assets"
+    ],
+    "additionalNpmPackages": [
+        {
+            "name": "gltf2interface",
+            "path": "dist/preview release/gltf2interface/"
+        }
+    ],
+    "core": {
+        "isCore": true,
+        "libraries": [
+            {
+                "output": "babylon.js",
+                "entry": "./Legacy/legacy.ts"
+            }
+        ],
+        "build": {
+            "mainFolder": "./src/",
+            "loseDTSFiles": {
+                "glob": "LibDeclarations/*.d.ts",
+                "destFileES6": "Engines/engine.d.ts"
+            },
+            "distOutputDirectory": "",
+            "packageJSON": "package.json",
+            "umd": {
+                "packageName": "babylonjs",
+                "webpackRoot": "BABYLON",
+                "processDeclaration": {
+                    "filename": "babylon.module.d.ts",
+                    "moduleName": "BABYLON",
+                    "moduleSpecifics": [
+                        {
+                            "path": "babylonjs/Debug/axesViewer",
+                            "namespace": "BABYLON.Debug"
+                        },
+                        {
+                            "path": "babylonjs/Debug/boneAxesViewer",
+                            "namespace": "BABYLON.Debug"
+                        },
+                        {
+                            "path": "babylonjs/Debug/physicsViewer",
+                            "namespace": "BABYLON.Debug"
+                        },
+                        {
+                            "path": "babylonjs/Debug/skeletonViewer",
+                            "namespace": "BABYLON.Debug"
+                        }
+                    ],
+                    "doNotAppendNamespace": true,
+                    "prependToNamespaceText": "declare module 'babylonjs' { export = BABYLON; }"
+                },
+                "packagesFiles": [
+                    "babylon.d.ts",
+                    "babylon.js",
+                    "babylon.max.js",
+                    "babylon.max.js.map",
+                    "Oimo.js",
+                    "readme.md"
+                ],
+                "typings": "babylon.d.ts",
+                "index": "babylon.js",
+                "dependencies": [],
+                "devDependencies": []
+            },
+            "es6": {
+                "packageName": "@babylonjs/core"
+            },
+            "requiredFiles": [
+                "readme.md"
+            ]
+        }
+    },
+    "materialsLibrary": {
+        "libraries": [
+            {
+                "output": "babylonjs.materials.min.js",
+                "entry": "./legacy/legacy.ts"
+            },
+            {
+                "output": "babylon.cellMaterial.min.js",
+                "entry": "./legacy/legacy-cell.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.customMaterial.min.js",
+                "entry": "./legacy/legacy-custom.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.fireMaterial.min.js",
+                "entry": "./legacy/legacy-fire.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.furMaterial.min.js",
+                "entry": "./legacy/legacy-fur.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.gradientMaterial.min.js",
+                "entry": "./legacy/legacy-gradient.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.gridMaterial.min.js",
+                "entry": "./legacy/legacy-grid.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.lavaMaterial.min.js",
+                "entry": "./legacy/legacy-lava.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.mixMaterial.min.js",
+                "entry": "./legacy/legacy-mix.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.normalMaterial.min.js",
+                "entry": "./legacy/legacy-normal.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.shadowOnlyMaterial.min.js",
+                "entry": "./legacy/legacy-shadowOnly.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.simpleMaterial.min.js",
+                "entry": "./legacy/legacy-simple.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.skyMaterial.min.js",
+                "entry": "./legacy/legacy-sky.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.terrainMaterial.min.js",
+                "entry": "./legacy/legacy-terrain.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.triPlanarMaterial.min.js",
+                "entry": "./legacy/legacy-triPlanar.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.waterMaterial.min.js",
+                "entry": "./legacy/legacy-water.ts",
+                "preventLoadLibrary": true
+            }
+        ],
+        "build": {
+            "mainFolder": "./materialsLibrary/",
+            "umd": {
+                "packageName": "babylonjs-materials",
+                "webpackRoot": "MATERIALS",
+                "processDeclaration": {
+                    "filename": "babylonjs.materials.module.d.ts",
+                    "moduleName": "BABYLON",
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON"
+                    }
+                }
+            },
+            "es6": {
+                "packageName": "@babylonjs/materials",
+                "requiredFiles": [
+                    "dist/preview release/materialsLibrary/readme.md"
+                ]
+            }
+        }
+    },
+    "postProcessesLibrary": {
+        "libraries": [
+            {
+                "output": "babylonjs.postProcess.min.js",
+                "entry": "./legacy/legacy.ts"
+            },
+            {
+                "output": "babylon.asciiArtPostProcess.min.js",
+                "entry": "./legacy/legacy-asciiArt.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.digitalRainPostProcess.min.js",
+                "entry": "./legacy/legacy-digitalRain.ts",
+                "preventLoadLibrary": true
+            }
+        ],
+        "build": {
+            "mainFolder": "./postProcessLibrary/",
+            "umd": {
+                "packageName": "babylonjs-post-process",
+                "webpackRoot": "POSTPROCESSES",
+                "processDeclaration": {
+                    "filename": "babylonjs.postProcess.module.d.ts",
+                    "moduleName": "BABYLON",
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON"
+                    }
+                }
+            },
+            "es6": {
+                "packageName": "@babylonjs/post-processes",
+                "requiredFiles": [
+                    "dist/preview release/postProcessesLibrary/readme.md"
+                ]
+            }
+        }
+    },
+    "proceduralTexturesLibrary": {
+        "libraries": [
+            {
+                "output": "babylonjs.proceduralTextures.min.js",
+                "entry": "./legacy/legacy.ts"
+            },
+            {
+                "output": "babylon.brickProceduralTexture.min.js",
+                "entry": "./legacy/legacy-brick.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.cloudProceduralTexture.min.js",
+                "entry": "./legacy/legacy-cloud.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.fireProceduralTexture.min.js",
+                "entry": "./legacy/legacy-fire.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.grassProceduralTexture.min.js",
+                "entry": "./legacy/legacy-grass.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.marbleProceduralTexture.min.js",
+                "entry": "./legacy/legacy-marble.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.normalMapProceduralTexture.min.js",
+                "entry": "./legacy/legacy-normalMap.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.perlinNoiseProceduralTexture.min.js",
+                "entry": "./legacy/legacy-perlinNoise.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.roadProceduralTexture.min.js",
+                "entry": "./legacy/legacy-road.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.starfieldProceduralTexture.min.js",
+                "entry": "./legacy/legacy-starfield.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.woodProceduralTexture.min.js",
+                "entry": "./legacy/legacy-wood.ts",
+                "preventLoadLibrary": true
+            }
+        ],
+        "build": {
+            "mainFolder": "./proceduralTexturesLibrary/",
+            "umd": {
+                "packageName": "babylonjs-procedural-textures",
+                "webpackRoot": "PROCEDURALTEXTURES",
+                "processDeclaration": {
+                    "filename": "babylonjs.proceduralTextures.module.d.ts",
+                    "moduleName": "BABYLON",
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON"
+                    }
+                }
+            },
+            "es6": {
+                "packageName": "@babylonjs/procedural-textures",
+                "requiredFiles": [
+                    "dist/preview release/proceduralTexturesLibrary/readme.md"
+                ]
+            }
+        }
+    },
+    "loaders": {
+        "libraries": [
+            {
+                "output": "babylonjs.loaders.min.js",
+                "entry": "./legacy/legacy.ts"
+            },
+            {
+                "output": "babylon.objFileLoader.min.js",
+                "entry": "./legacy/legacy-objFileLoader.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.stlFileLoader.min.js",
+                "entry": "./legacy/legacy-stlFileLoader.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.glTF1FileLoader.min.js",
+                "entry": "./legacy/legacy-glTF1FileLoader.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.glTF2FileLoader.min.js",
+                "entry": "./legacy/legacy-glTF2FileLoader.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.glTFFileLoader.min.js",
+                "entry": "./legacy/legacy-glTFFileLoader.ts",
+                "preventLoadLibrary": true
+            }
+        ],
+        "build": {
+            "mainFolder": "./loaders/",
+            "umd": {
+                "packageName": "babylonjs-loaders",
+                "webpackRoot": "LOADERS",
+                "processDeclaration": {
+                    "filename": "babylonjs.loaders.module.d.ts",
+                    "moduleName": "BABYLON",
+                    "moduleSpecifics": [
+                        {
+                            "path": "babylonjs-loaders/glTF/1.0",
+                            "namespace": "BABYLON.GLTF1"
+                        },
+                        {
+                            "path": "babylonjs-loaders/glTF/2.0",
+                            "namespace": "BABYLON.GLTF2"
+                        },
+                        {
+                            "path": "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces",
+                            "namespace": "BABYLON.GLTF2.Loader"
+                        },
+                        {
+                            "path": "babylonjs-loaders/glTF/2.0/Extensions",
+                            "namespace": "BABYLON.GLTF2.Loader.Extensions"
+                        }
+                    ],
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON",
+                        "babylonjs-gltf2interface": "BABYLON.GLTF2"
+                    }
+                }
+            },
+            "es6": {
+                "packageName": "@babylonjs/loaders",
+                "requiredFiles": [
+                    "dist/preview release/loaders/readme.md"
+                ]
+            }
+        }
+    },
+    "serializers": {
+        "libraries": [
+            {
+                "output": "babylonjs.serializers.min.js",
+                "entry": "./legacy/legacy.ts"
+            },
+            {
+                "output": "babylon.objSerializer.min.js",
+                "entry": "./legacy/legacy-objSerializer.ts",
+                "preventLoadLibrary": true
+            },
+            {
+                "output": "babylon.glTF2Serializer.min.js",
+                "entry": "./legacy/legacy-glTF2Serializer.ts",
+                "preventLoadLibrary": true
+            }
+        ],
+        "build": {
+            "mainFolder": "./serializers/",
+            "umd": {
+                "packageName": "babylonjs-serializers",
+                "webpackRoot": "SERIALIZERS",
+                "processDeclaration": {
+                    "filename": "babylonjs.serializers.module.d.ts",
+                    "moduleName": "BABYLON",
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON",
+                        "babylonjs-loaders": "BABYLON",
+                        "babylonjs-serializers": "BABYLON",
+                        "babylonjs-gltf2interface": "BABYLON.GLTF2"
+                    },
+                    "moduleSpecifics": [
+                        {
+                            "path": "babylonjs-serializers/glTF/2.0",
+                            "namespace": "BABYLON.GLTF2.Exporter"
+                        },
+                        {
+                            "path": "babylonjs-serializers/glTF/2.0/Extensions",
+                            "namespace": "BABYLON.GLTF2.Exporter.Extensions"
+                        },
+                        {
+                            "path": "babylonjs-serializers/glTF/2.0/glTFData",
+                            "namespace": "BABYLON"
+                        },
+                        {
+                            "path": "babylonjs-serializers/glTF/2.0/glTFSerializer",
+                            "namespace": "BABYLON"
+                        }
+                    ]
+                }
+            },
+            "es6": {
+                "packageName": "@babylonjs/serializers",
+                "requiredFiles": [
+                    "dist/preview release/serializers/readme.md"
+                ]
+            }
+        }
+    },
+    "gui": {
+        "libraries": [
+            {
+                "output": "babylon.gui.min.js",
+                "entry": "./legacy/legacy.ts"
+            }
+        ],
+        "build": {
+            "mainFolder": "./gui/",
+            "umd": {
+                "packageName": "babylonjs-gui",
+                "webpackRoot": "BABYLON.GUI",
+                "processDeclaration": {
+                    "filename": "babylon.gui.module.d.ts",
+                    "moduleName": "BABYLON.GUI",
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON",
+                        "babylonjs-loaders": "BABYLON",
+                        "babylonjs-serializers": "BABYLON"
+                    }
+                }
+            },
+            "es6": {
+                "packageName": "@babylonjs/gui",
+                "requiredFiles": [
+                    "dist/preview release/gui/readme.md"
+                ]
+            }
+        }
+    },
+    "inspector": {
+        "libraries": [
+            {
+                "output": "babylon.inspector.bundle.js",
+                "entry": "./legacy/legacy.ts"
+            }
+        ],
+        "build": {
+            "ignoreInTestMode": true,
+            "mainFolder": "./inspector/",
+            "umd": {
+                "packageName": "babylonjs-inspector",
+                "webpackRoot": "INSPECTOR",
+                "processDeclaration": {
+                    "filename": "babylon.inspector.module.d.ts",
+                    "moduleName": "INSPECTOR",
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON",
+                        "babylonjs-loaders": "BABYLON",
+                        "babylonjs-serializers": "BABYLON",
+                        "babylonjs-gltf2interface": "BABYLON.GLTF2",
+                        "react": "React",
+                        "babylonjs-gui": "BABYLON.GUI",
+                        "@babylonjs/core": "BABYLON",
+                        "@babylonjs/loaders": "BABYLON",
+                        "@babylonjs/serializers": "BABYLON",
+                        "@babylonjs/gui": "BABYLON.GUI",
+                        "@fortawesome": false
+                    }
+                }
+            },
+            "es6": {
+                "webpackBuild": {
+                    "dependencies": [
+                        "node_modules/re-resizable/lib/index.es5.js",
+                        "Tools/**/*"
+                    ]
+                },
+                "packageName": "@babylonjs/inspector",
+                "requiredFiles": [
+                    "dist/preview release/inspector/readme.md"
+                ],
+                "packagesFiles": [
+                    "babylon.inspector.bundle.max.js",
+                    "babylon.inspector.bundle.max.js.map",
+                    "babylon.inspector.module.d.ts",
+                    "readme.md"
+                ],
+                "typings": "babylon.inspector.module.d.ts",
+                "index": "babylon.inspector.bundle.max.js"
+            }
+        }
+    },
+    "viewer": {
+        "libraries": [
+            {
+                "output": "babylon.viewer.js",
+                "moduleDeclaration": {
+                    "name": "BabylonViewer",
+                    "module": "babylonjs-viewer"
+                },
+                "preventLoadLibrary": true
+            }
+        ],
+        "build": {
+            "webpack": "../../../Viewer/webpack.gulp.config.js",
+            "distOutputDirectory": "/viewer/",
+            "dtsBundle": {
+                "name": "babylonjs-viewer",
+                "main": "../../dist/preview release/viewer/build/src/index.d.ts",
+                "out": "../../babylon.viewer.module.d.ts"
+            },
+            "umd": {
+                "packageName": "babylonjs-viewer",
+                "processDeclaration": {
+                    "moduleName": "BabylonViewer",
+                    "doNotAppendNamespace": true,
+                    "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",
+                    "importsToRemove": [
+                        "pep",
+                        "babylonjs-loaders"
+                    ],
+                    "classMap": {
+                        "babylonjs": "BABYLON",
+                        "babylonjs-loaders": "BABYLON"
+                    }
+                }
+            },
+            "outputs": [
+                {
+                    "destinations": [
+                        {
+                            "filename": "viewer.js",
+                            "outputDirectory": "/../../Viewer/dist/"
+                        },
+                        {
+                            "filename": "babylon.viewer.js",
+                            "outputDirectory": "/viewer/",
+                            "addBabylonDeclaration": [
+                                "babylon.d.ts",
+                                "loaders/babylonjs.loaders.d.ts",
+                                "glTF2Interface/babylon.glTF2Interface.d.ts"
+                            ]
+                        }
+                    ],
+                    "minified": true
+                },
+                {
+                    "destinations": [
+                        {
+                            "filename": "viewer.max.js",
+                            "outputDirectory": "/../../Viewer/dist/"
+                        },
+                        {
+                            "filename": "babylon.viewer.max.js",
+                            "outputDirectory": "/viewer/"
+                        }
+                    ]
+                }
+            ],
+            "legacyPackageOutputDirectory": "../../../Viewer/build/src/",
+            "requiredFiles": [
+                "dist/preview release/viewer/readme.md",
+                "dist/preview release/viewer/package.json",
+                "dist/preview release/viewer/babylon.viewer.js",
+                "dist/preview release/viewer/babylon.viewer.max.js"
+            ]
+        }
+    },
+    "viewer-assets": {
+        "libraries": [
+            {
+                "output": "babylon.viewer.assets.js",
+                "moduleDeclaration": {
+                    "name": "BabylonViewerAssets",
+                    "module": "babylonjs-viewer-assets"
+                },
+                "preventLoadLibrary": true
+            }
+        ],
+        "build": {
+            "webpack": "../../../Viewer/webpack.assets.config.js",
+            "distOutputDirectory": "/viewer/",
+            "umd": {
+                "packageName": "babylonjs-viewer-assets"
+            },
+            "dtsBundle": {
+                "name": "babylonjs-viewer-assets",
+                "main": "../../dist/preview release/viewer/build/src/assets/index.d.ts",
+                "out": "../../../../../../Viewer/build/assets/babylon.viewer.assets.module.d.ts"
+            },
+            "outputs": [
+                {
+                    "destinations": [
+                        {
+                            "filename": "babylon.viewer.assets.js",
+                            "outputDirectory": "/../../Viewer/build/assets/"
+                        }
+                    ],
+                    "minified": true
+                }
+            ],
+            "legacyPackageOutputDirectory": "../../../Viewer/build/assets/",
+            "requiredFiles": [
+                "Viewer/assets/readme.md",
+                "Viewer/assets/package.json"
+            ]
+        }
+    }
+}

+ 57 - 91
Tools/DevLoader/BabylonLoader.js

@@ -28,6 +28,7 @@ var BABYLONDEVTOOLS;
 
     var Loader = (function() {
         var queue;
+        var esmQueue;
         var callback;
         var dependencies;
         var useDist;
@@ -35,8 +36,12 @@ var BABYLONDEVTOOLS;
         var min;
         var babylonJSPath;
 
+        var localDevES6FolderName;
+        var localDevUMDFolderName;
+
         function Loader() {
             queue = [];
+            esmQueue = [];
             dependencies = [];
             callback = null;
             min = (document.location.href.toLowerCase().indexOf('dist=min') > 0);
@@ -103,7 +108,7 @@ var BABYLONDEVTOOLS;
         }
 
         Loader.prototype.dequeue = function() {
-            if (queue.length == 0) {
+            if (queue.length + esmQueue.length == 0) {
                 console.log('Scripts loaded');
                 BABYLON.Engine.ShadersRepository = "/src/Shaders/";
                 if (callback) {
@@ -112,12 +117,17 @@ var BABYLONDEVTOOLS;
                 return;
             }
 
-            var url = queue.shift();
-
             var head = document.getElementsByTagName('head')[0];
             var script = document.createElement('script');
-            script.type = 'text/javascript';
-            script.src = url;
+
+            if (esmQueue.length) {
+                script.type = 'module';
+                script.src = esmQueue.shift();
+            }
+            else {
+                script.type = 'text/javascript';
+                script.src = queue.shift();
+            }
 
             var self = this;
             script.onload = function() {
@@ -130,9 +140,11 @@ var BABYLONDEVTOOLS;
             queue.push(url);
         }
 
-        Loader.prototype.loadCss = function(url) {
-            var head = document.getElementsByTagName('head')[0];
+        Loader.prototype.loadESMScript = function(url) {
+            esmQueue.push(url);
+        }
 
+        Loader.prototype.loadCss = function(url) {
             var style = document.createElement('link');
             style.href = url;
             style.rel = "stylesheet";
@@ -146,70 +158,51 @@ var BABYLONDEVTOOLS;
             }
         }
 
-        Loader.prototype.loadLibrary = function(library, module) {
+        Loader.prototype.loadLibrary = function(moduleName, library, module) {
             if (library.preventLoadLibrary) {
                 return;
             }
 
+            var distFolder = (module.build.distOutputDirectory !== undefined) ?
+                module.build.distOutputDirectory :
+                "/" + moduleName;
+            distFolder += "/";
+            
             if (!useDist) {
-                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;
-                        }
-                        // Manage exclude files.
-                        if (library.excludeFromLoader && library.excludeFromLoader.indexOf(file) > -1) {
-                            continue;
-                        }
-
-                        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);
-                        }
-                    }
-                }
+                var tempDirectory = '/.temp/' + localDevUMDFolderName + distFolder;
+                this.loadScript((babylonJSPath + tempDirectory + library.output)
+                    .replace(".min.", ".")
+                    .replace(".max.", "."));
             }
-            else if (min) {
-                if (library.webpack) {
-                    if (module.build.distOutputDirectory)
-                        this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output);
+            else if (!testMode || !module.build.ignoreInTestMode) {
+                if (min) {
+                    this.loadScript(babylonJSPath + '/dist/preview release' + distFolder + library.output);
                 }
                 else {
-                    this.loadScript(babylonJSPath + '/dist/preview release' + module.build.distOutputDirectory + library.output.replace('.js', '.min.js'));
+                    var isMinOutputName = library.output.indexOf(".min.") > -1;
+                    if (isMinOutputName) {
+                        this.loadScript(babylonJSPath + '/dist/preview release' + distFolder + library.output.replace(".min", ""));
+                    }
+                    else {
+                        this.loadScript(babylonJSPath + '/dist/preview release' + distFolder + library.output.replace(".js", ".max.js"));
+                    }
                 }
             }
-            else {
-                if (module.build.distOutputDirectory && (!testMode || !module.build.ignoreInTestMode))
-                    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;
-                this.loadCss(cssFile);
-            }
+        Loader.prototype.loadCoreDev = function() {
+            // Es6 core import
+            this.loadESMScript(babylonJSPath + "/.temp/" + localDevES6FolderName + "/core/legacy/legacy.js");
         }
 
-        Loader.prototype.loadModule = function(module) {
+        Loader.prototype.loadModule = function(moduleName, module) {
             for (var i = 0; i < module.libraries.length; i++) {
-                this.loadLibrary(module.libraries[i], module);
+                if (!useDist && module.isCore) {
+                    this.loadCoreDev();
+                }
+                else {
+                    this.loadLibrary(moduleName, module.libraries[i], module);
+                }
             }
         }
 
@@ -232,39 +225,9 @@ var BABYLONDEVTOOLS;
         }
 
         Loader.prototype.loadBJSScripts = function(settings) {
-            var loadModules = true;
-
-            // Main bjs files
-            if (!useDist) {
-                var currentConfig = settings.build.currentConfig;
-                var buildConfiguration = settings.buildConfigurations[currentConfig];
-                var filesToLoad = [];
-
-                for (var index = 0; index < buildConfiguration.length; index++) {
-                    var dependencyName = buildConfiguration[index];
-                    var dependency = settings.workloads[dependencyName];
-                    this.processDependency(settings, dependency, filesToLoad);
-                }
-
-                this.loadScripts(filesToLoad);
-
-                if (currentConfig !== "all") {
-                    loadModules = false;
-                }
-            }
-            else if (min) {
-                this.loadScript('/dist/preview release/babylon.js');
-            }
-            else {
-                this.loadScript('/dist/preview release/babylon.max.js');
-            }
-
-            // Modules
-            if (loadModules) {
-
-                for (var i = 0; i < settings.modules.length; i++) {
-                    this.loadModule(settings[settings.modules[i]]);
-                }
+            // Load all the modules from the config.json.
+            for (var i = 0; i < settings.modules.length; i++) {
+                this.loadModule(settings.modules[i], settings[settings.modules[i]]);
             }
         }
 
@@ -273,8 +236,11 @@ var BABYLONDEVTOOLS;
             if (newCallback) {
                 callback = newCallback;
             }
-            getJson('/Tools/Gulp/config.json',
+            getJson('/Tools/Config/config.json',
                 function(data) {
+                    localDevES6FolderName = data.build.localDevES6FolderName;
+                    localDevUMDFolderName = data.build.localDevUMDFolderName;
+
                     self.loadBJSScripts(data);
                     if (dependencies) {
                         self.loadScripts(dependencies);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 2132
Tools/Gulp/config.json


+ 0 - 58
Tools/Gulp/gulp-addDtsExport.js

@@ -1,58 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-
-module.exports = function (varName, moduleName, subModule, extendsRoot, dependencies) {
-    return through.obj(function (file, enc, cb) {
-
-        let exportText = "BABYLON";
-        if (subModule && !extendsRoot) {
-            exportText += '.' + varName.name;
-        }
-
-        let referenceText = '';
-        if (subModule) {
-            //referenceText = '/// <reference types="babylonjs"/>\n';
-        }
-
-        if (dependencies) {
-            referenceText = '';
-            dependencies.forEach(element => {
-                // was "babylonjs/${element}""
-                referenceText += `/// <reference types="${element}"/>
-`;
-            });
-        }
-
-        var moduleExportsAddition =
-            `${referenceText}
-
-declare module '${moduleName}' { 
-    export = ${exportText}; 
-}
-`;
-
-        //'export = ' + (subModule ? 'BABYLON.' : '') + varName + ';\n';// +
-        //'export as namespace ' + varName + ';\n\n';
-
-
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-
-        if (file.isStream()) {
-            //streams not supported, no need for now.
-            return;
-        }
-
-        try {
-            file.contents = Buffer.from(moduleExportsAddition + String(file.contents));
-            this.push(file);
-
-        } catch (err) {
-            this.emit('error', new gutil.PluginError('gulp-add-module-exports', err, { fileName: file.path }));
-        }
-        cb();
-    });
-};
-

+ 0 - 89
Tools/Gulp/gulp-addES6Exports.js

@@ -1,89 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-
-/**
- * The parameters for this function has grown during development.
- * Eventually, this function will need to be reorganized. 
- */
-module.exports = function (baseModule, subModule, extendsRoot, externalUsingBabylon) {
-    return through.obj(function (file, enc, cb) {
-
-        var optionalRequire = `var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-var babylonDependency = (globalObject && globalObject.BABYLON) || BABYLON || (typeof require !== 'undefined' && require("babylonjs"));
-var BABYLON = babylonDependency;
-`;
-        let fileContent = file.contents.toString();
-        function moduleExportAddition(varName) {
-
-            let base = subModule ? 'BABYLON' : baseModule;
-
-            let sadGlobalPolution = (!subModule) ? `var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-globalObject["${base}"] = ${base}${(subModule && !extendsRoot) ? '.' + varName : ''};` : '';
-            /*if (extendsRoot) {
-                basicInit = `__extends(root["BABYLON"], factory()); `
-            }*/
-
-            let listOfExports = [];
-            // find the exported members. es6 exports can NOT be generated dynamically.
-            let matcher = new RegExp(base + "\\.(\\w*) = (\\w*);", "g");
-            let match = matcher.exec(fileContent);
-            while (match != null) {
-                if (match[1] && match[2] && match[1] === match[2]) {
-                    listOfExports.push(match[1]);
-                }
-                match = matcher.exec(fileContent);
-            }
-
-            let enumMatcher = new RegExp(`\\(${base}\\.([A-Za-z0-9].*)= {}\\)`, "g");
-            let enumMatch = enumMatcher.exec(fileContent);
-            while (enumMatch != null) {
-                if (enumMatch[1] && listOfExports.indexOf(enumMatch[1]) === -1) {
-                    listOfExports.push(enumMatch[1]);
-                }
-                enumMatch = enumMatcher.exec(fileContent);
-            }
-
-
-            let exportsText = '';
-            listOfExports.forEach(cls => {
-                exportsText += `var ${cls} = ${base}.${cls};`;
-            });
-            exportsText += `
-export { ${listOfExports.join(",")} };`
-
-            return `${sadGlobalPolution}
-${exportsText}
-`;
-        }
-
-        var extendsAddition = `var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
-`;
-
-        var decorateAddition = 'var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};\n';
-
-
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-
-        if (file.isStream()) {
-            //streams not supported, no need for now.
-            return;
-        }
-
-        try {
-            if (externalUsingBabylon) {
-                //file.contents = new Buffer(optionalRequire.concat(String(file.contents)));
-                file.contents = Buffer.from(optionalRequire.concat(Buffer.from(String(file.contents).concat(moduleExportAddition(baseModule)))));
-            } else {
-                let pretext = subModule ? optionalRequire : '';
-                file.contents = Buffer.from(pretext.concat(decorateAddition).concat(Buffer.from(extendsAddition.concat(String(file.contents)).concat(moduleExportAddition(baseModule)))));
-            }
-            this.push(file);
-        } catch (err) {
-            this.emit('error', new gutil.PluginError('gulp-add-module-exports', err, { fileName: file.path }));
-        }
-        cb();
-    });
-};

+ 0 - 113
Tools/Gulp/gulp-addModuleExports.js

@@ -1,113 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-
-/**
- * The parameters for this function has grown during development.
- * Eventually, this function will need to be reorganized. 
- */
-//  subModule, extendsRoot, externalUsingBabylon, noBabylonInit
-module.exports = function (varName, config) {
-    return through.obj(function (file, enc, cb) {
-        config = config || {};
-        if (typeof varName === 'string') {
-            varName = {
-                name: varName,
-                module: varName
-            }
-            if (varName.name === 'BABYLON') {
-                varName.module = 'babylonjs';
-            }
-        }
-        if (!config.dependencies) {
-            if (config.subModule || config.extendsRoot) {
-                config.dependencies = [
-                    {
-                        name: "BABYLON",
-                        module: "babylonjs",
-                        optional: false
-                    }
-                ]
-            }
-        }
-
-        function moduleExportAddition(varName) {
-
-            let dependenciesDefinition = `var amdDependencies = [];`;
-            let functionVariables = '';
-            let requireText = '';
-            let amdText = '';
-            let afterInitText = '';
-            if (config.dependencies) {
-                config.dependencies.forEach(dep => {
-                    if (functionVariables) functionVariables += ',';
-                    functionVariables += dep.name;
-                    requireText += `        ${dep.optional ? ' try { ' : ''} ${dep.name} = ${dep.name} || require("${dep.module}"); ${dep.optional ? ' } catch(e) {} ' : ''}
-`;
-                    amdText += `        ${dep.optional ? ' if(require.specified && require.specified("' + dep.module + '"))' : ''} amdDependencies.push("${dep.module}");
-`;
-                    dependenciesDefinition += `
-    var ${dep.name} = root.${dep.name} || this.${dep.name};`;
-                    afterInitText += `  ${dep.name} = ${dep.name} || this.${dep.name};
-`
-                });
-
-            }
-
-            let base = config.subModule ? 'BABYLON' : varName.name;
-
-            return `\n\n(function universalModuleDefinition(root, factory) {
-    ${dependenciesDefinition}
-    if(typeof exports === 'object' && typeof module === 'object') {
-${requireText}
-        module.exports = factory(${functionVariables});
-    } else if(typeof define === 'function' && define.amd) {
-${amdText}
-        define("${varName.module}", amdDependencies, factory);
-    } else if(typeof exports === 'object') {
-${requireText}
-        exports["${varName.module}"] = factory(${functionVariables});
-    } else {
-        root["${base}"]${(config.subModule && !config.extendsRoot) ? '["' + varName.name + '"]' : ''} = factory(${functionVariables});
-    }
-})(this, function(${functionVariables}) {
-${afterInitText}
-${String(file.contents)}
-    ${varName.name === 'BABYLON' || varName.name === 'INSPECTOR' ? `
-var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-globalObject["${varName.name}"] = ${varName.name};
-//backwards compatibility
-if(typeof earcut !== 'undefined') {
-    globalObject["Earcut"] = {
-        earcut: earcut
-    };
-}` : ''}
-
-    return ${base}${(config.subModule && !config.extendsRoot) ? '.' + varName.name : ''};
-});
-`;
-        }
-
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-
-        if (file.isStream()) {
-            //streams not supported, no need for now.
-            return;
-        }
-
-        try {
-            //if (config.externalUsingBabylon) {
-            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)))));
-            }*/
-            this.push(file);
-        } catch (err) {
-            this.emit('error', new gutil.PluginError('gulp-add-module-exports', err, { fileName: file.path }));
-        }
-        cb();
-    });
-};

+ 0 - 99
Tools/Gulp/gulp-appendSrcToVariable.js

@@ -1,99 +0,0 @@
-var through = require('through2');
-var gutil = require('gulp-util');
-var PluginError = gutil.PluginError;
-var path = require('path');
-var File = gutil.File;
-
-// Consts
-const PLUGIN_NAME = 'gulp-appendSrcToVariable';
-
-var appendSrcToVariable = function appendSrcToVariable(varName, namingCallback, output, moduleType) {
-
-    var content;
-    var firstFile;
-
-    namingCallback = namingCallback || function (filename) { return filename; };
-
-    function bufferContents(file, enc, cb) {
-        // ignore empty files
-        if (file.isNull()) {
-            cb();
-            return;
-        }
-
-        // no stream support, only files.
-        if (file.isStream()) {
-            this.emit('error', new PluginError('gulp-concat', 'Streaming not supported'));
-            cb();
-            return;
-        }
-
-        // construct concat instance
-        if (!content) {
-            content = "";
-        }
-
-        // set first file if not already set
-        if (!firstFile) {
-            if (moduleType === "es6") {
-                content += `
-// import * as BABYLON from 'babylonjs/core/es6';
-`;
-            }
-            firstFile = file;
-        }
-
-
-        var name = namingCallback(file.relative);
-        if (moduleType) {
-            let vars = varName.split(".");
-            // shader support when using modules
-            if (moduleType === "es6") {
-                content += `
-let ${name} = ${JSON.stringify(file.contents.toString())};
-// ${varName}["${name}"] = ${varName}["${name}"] || ${name};
-export { ${name}  };
-`;
-            } else {
-                // commonjs
-                content += `
-if(typeof require !== 'undefined'){
-var BABYLON = require("babylonjs/core");
-let data = ${JSON.stringify(file.contents.toString())};
-${varName}["${name}"] = ${varName}["${name}"] || data;
-module.exports = module.exports || {};
-module.exports["${name}"] = data;
-}
-`;
-            }
-        } else {
-            content += varName + "['" + name + "'] = " + JSON.stringify(file.contents.toString()) + ";\r\n";
-        }
-        cb();
-    }
-
-    function endStream(cb) {
-        if (!firstFile || !content) {
-            cb();
-            return;
-        }
-
-        var pathObject = path.parse(firstFile.path);
-        var joinedPath = path.join(pathObject.dir, output);
-
-        var joinedFile = new File({
-            cwd: firstFile.cwd,
-            base: firstFile.base,
-            path: joinedPath,
-            contents: Buffer.from(content)
-        });
-
-        this.push(joinedFile);
-
-        cb();
-    }
-
-    return through.obj(bufferContents, endStream);
-}
-
-module.exports = appendSrcToVariable;

+ 0 - 133
Tools/Gulp/gulp-babylonModule.js

@@ -1,133 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-var path = require('path');
-
-module.exports = function (moduleName, dependencyTree, generateIndex, perFile, shaders, shaderIncludes) {
-    return through.obj(function (file, enc, cb) {
-
-        let basename = (path.basename(file.path, ".js"));
-
-        //console.log("Compiling module: " + moduleName + "/" + basename.replace("babylon.", ""));
-
-        var extendsAddition =
-            `var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
-`;
-
-        var decorateAddition =
-            'var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};\n';
-
-        let content = file.contents.toString();
-        if (content.indexOf('__extends') === -1 && !dependencyTree.length) {
-            extendsAddition = '';
-        }
-
-        if (content.indexOf('__decorate') === -1) {
-            decorateAddition = '';
-        }
-
-        let dependenciesText = `${extendsAddition}
-${decorateAddition}
-if(typeof require !== 'undefined'){
-    var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-    var BABYLON = globalObject["BABYLON"] || {}; 
-    var EXPORTS = {};
-`;
-        let exportsText = '';
-        if (!generateIndex) {
-            let loadedFiles = [];
-            dependencyTree[basename].forEach(function (d, idx) {
-                if (d.module.indexOf("core") !== -1) return;
-                let name = d.file.split(".").pop();
-
-                if (loadedFiles.indexOf(name) === -1) {
-                    if (d.main)
-                        dependenciesText += `var ${name}Module = require('babylonjs/${d.module[0]}/${name}');
-`;
-                    else
-                        exportsText += `var ${name}Module = require('babylonjs/${d.module[0]}/${name}');
-`;
-                    loadedFiles.push(name);
-                }
-
-                dependenciesText += `BABYLON["${d.name}"] = ${name}Module["${d.name}"];
-`;
-                //dependenciesText += `if(BABYLON !== BABYLON${idx}) __extends(BABYLON, BABYLON${idx});
-            });
-            perFile[basename].declarations.forEach(dec => {
-                exportsText += `EXPORTS['${dec}'] = BABYLON["${dec}"];
-`;
-            });
-            if (shaders) {
-                dependenciesText += `require("babylonjs/${moduleName}/shaders");
-`;
-            }
-            if (shaderIncludes) {
-                dependenciesText += `require("babylonjs/${moduleName}/shaderIncludes");
-`;
-            }
-        } else {
-            content = '';
-            let basenames = Object.keys(perFile).filter(basefilename => {
-                return perFile[basefilename].module.indexOf(moduleName) !== -1;
-            });
-
-            basenames.forEach(bname => {
-                let name = bname.split(".").pop();
-                dependenciesText += `var ${name} = require("babylonjs/${moduleName}/${name}");
-`;
-                // now add the internal dependencies to EXPORTS
-                perFile[bname].declarations.forEach(dec => {
-                    dependenciesText += `EXPORTS['${dec}'] = BABYLON["${dec}"] = ${name}["${dec}"];
-`;
-                });
-            })
-        }
-
-        exportsText += `(function() {
-    globalObject["BABYLON"] = globalObject["BABYLON"] || BABYLON;
-    module.exports = EXPORTS;
-    })();
-}`;
-
-
-
-        /*let exportRegex = /BABYLON.([0-9A-Za-z-_]*) = .*;\n/g
-
-        var match = exportRegex.exec(content);
-
-        let exportsArray = [];
-        while (match != null) {
-            if (match[1]) {
-                exportsArray.push(match[1])
-            }
-            match = exportRegex.exec(content);
-        }*/
-
-
-        /*if (moduleName === "core") {
-            exportsText = `(function() {
-    globalObject["BABYLON"] = globalObject["BABYLON"] || BABYLON;
-    module.exports = BABYLON; 
-})();
-}`
-        }*/
-
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-
-        if (file.isStream()) {
-            //streams not supported, no need for now.
-            return;
-        }
-
-        try {
-            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 }));
-        }
-        cb();
-    });
-}

+ 0 - 80
Tools/Gulp/gulp-calculateDependencies.js

@@ -1,80 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-var path = require('path');
-
-module.exports = function (moduleName, perFile, declared, depTree) {
-    return through.obj(function (file, enc, cb) {
-        let basename = (path.basename(file.path, ".ts"));
-        depTree[basename] = depTree[basename] || [];
-        // detect dependencies
-        let depReg1 = /[:,][ ]{0,1}([A-Z]\w*)/g;
-        let depReg2 = /<([A-Z]\w*)(\[\]){0,1}>/g;
-        let depReg3 = /[\s(]([A-Z]\w*)\./g;
-        let depReg4 = /[extends|implements] ([A-Z]\w*)/g;
-        let depReg5 = /new ([A-Z]\w*)/g;
-
-        let dependencies = [];
-        fileContent = file.contents.toString().replace(/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm, "");
-        function findWhereDeclared(objectName) {
-            let fileLocator;
-            Object.keys(perFile).some((filename => {
-                filedec = perFile[filename];
-                if (filedec.declarations.indexOf(objectName) !== -1) {
-                    fileLocator = filename;
-                    return true;
-                }
-                return false;
-            }))
-            return fileLocator;
-        }
-
-        //if (basename === "babylon.webVRCamera") {
-        [depReg4, depReg1, depReg5, depReg3, depReg2].forEach((reg, idx) => {
-            var match = reg.exec(fileContent);
-            while (match != null) {
-                if (match[1]) {
-                    let dep = match[1];
-                    if (basename === "babylon.poseEnabledController") {
-                        console.log(dep, idx);
-                    }
-                    //find if it is declared internally
-                    if (perFile[basename].declarations.indexOf(dep) === -1) {
-                        // not internally? maybe it is in core?
-                        //if (declared.core.indexOf(dep) === -1) {
-                        // seems like a legit dependency! was it already added?
-                        if (perFile[basename].dependencies.indexOf(dep) === -1) {
-                            //no! add it.
-                            let whereDeclared = (findWhereDeclared(dep));
-                            if (whereDeclared) {
-                                perFile[basename].dependencies.push(dep);
-                                if (basename === "babylon.poseEnabledController") {
-                                    console.log("adding ", dep, idx === 2);
-                                }
-                                depTree[basename].push({
-                                    name: dep,
-                                    file: whereDeclared,
-                                    module: perFile[whereDeclared].module,
-                                    main: idx === 0, // is it a main import
-                                    newDec: idx === 2 // is it "new"
-                                });
-                            }
-                        }
-                        //}
-                    }
-                }
-                match = reg.exec(fileContent);
-            }
-        });
-        //}
-
-
-        try {
-            this.push(file);
-
-        } catch (err) {
-            this.emit('error', new gutil.PluginError('gulp-calculateDependencies', err, { fileName: file.path }));
-        }
-        cb();
-    });
-};
-

+ 0 - 37
Tools/Gulp/gulp-decorateAndExtends.js

@@ -1,37 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-
-/**
- * The parameters for this function has grown during development.
- * Eventually, this function will need to be reorganized. 
- */
-//  subModule, extendsRoot, externalUsingBabylon, noBabylonInit
-module.exports = function (varName, config) {
-    return through.obj(function (file, enc, cb) {
-
-        var extendsAddition =
-            `var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
-`;
-
-        var decorateAddition = `var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};
-`;
-
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-
-        if (file.isStream()) {
-            //streams not supported, no need for now.
-            return;
-        }
-
-        try {
-            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 }));
-        }
-        cb();
-    });
-};

+ 0 - 96
Tools/Gulp/gulp-dtsModuleSupport.js

@@ -1,96 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-var path = require('path');
-
-// inject - if set to true, it will add all declarations as imports.
-module.exports = function (moduleName, inject, declarations, perFile, dependencyTree) {
-    return through.obj(function (file, enc, cb) {
-        let basename = (path.basename(file.path, ".d.ts"));
-        let fileContent = file.contents.toString();
-        let importsString = '';
-
-        if (!inject) {
-            perFile[basename] = perFile[basename] || {
-                module: [moduleName],
-                dependencies: [],
-                declarations: []
-            };
-            if (perFile[basename].module.indexOf(moduleName) === -1) {
-                perFile[basename].module.push(moduleName);
-            }
-            declarations[moduleName] = declarations[moduleName] || [];
-            let regexp = /    (abstract class|function|class|interface|type|const|enum|var) ([\w]*)/g;
-
-            var match = regexp.exec(fileContent);
-            while (match != null) {
-                if (match[2]) {
-                    // check it is not SIMD:
-                    let simdMatch = /    interface (\w*\dx\d{1,2}\w*)/.exec(match[0]);
-                    if (!simdMatch && match[2] !== 'earcut' && match[2] !== 'deviation' && match[2] !== 'flatten') {
-                        declarations[moduleName].push(match[2]);
-                        perFile[basename].declarations.push(match[2]);
-                    }
-                }
-                match = regexp.exec(fileContent);
-            }
-        } else {
-            /*let declared = [];
-            Object.keys(declarations).forEach(name => {
-                if (name === moduleName) return;
-                let imports = declarations[name].filter(obj => {
-                    let exists = declared.indexOf(obj) !== -1;
-                    if (!exists) {
-                        declared.push(obj);
-                    }
-                    return !exists;
-                });
-                if (imports.length)
-                    importsString += `import {${imports.join(',')}} from 'babylonjs/${name}';
-`;
-            });*/
-
-            // find all of the related files for the dependency tree integration
-            let basenames = Object.keys(perFile).filter(basefilename => {
-                return perFile[basefilename].module.indexOf(moduleName) !== -1;
-            });
-
-            let classesForImports = {} // key : module name, content - array of objects
-            basenames.forEach(bname => {
-                dependencyTree[bname].forEach(dep => {
-                    if (dep.module.indexOf(moduleName) !== -1) return;
-                    let depModule = dep.module.indexOf("core") === -1 ? dep.module[0] : "core";
-                    classesForImports[depModule] = classesForImports[depModule] || [];
-                    if (classesForImports[depModule].indexOf(dep.name) === -1) {
-                        //babylon.imageProcessingPostProcess
-                        classesForImports[depModule].push(dep.name);
-                    }
-                });
-            });
-
-            Object.keys(classesForImports).forEach(modName => {
-                importsString += `import {${classesForImports[modName].join(',')}} from 'babylonjs/${modName}';
-`;
-            });
-        }
-
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-
-        if (file.isStream()) {
-            //streams not supported, no need for now.
-            return;
-        }
-
-        try {
-            file.contents = Buffer.from(String(file.contents) + '\n' + importsString);
-            this.push(file);
-
-        } catch (err) {
-            this.emit('error', new gutil.PluginError('gulp-add-module-exports', err, { fileName: file.path }));
-        }
-        cb();
-    });
-};
-

+ 0 - 214
Tools/Gulp/gulp-es6ModuleExports.js

@@ -1,214 +0,0 @@
-var gutil = require('gulp-util');
-var through = require('through2');
-var path = require('path');
-
-module.exports = function (moduleName, dependencyTree, generateIndex, perFile, shaders, shaderIncludes) {
-    return through.obj(function (file, enc, cb) {
-
-        let basename = (path.basename(file.path, ".js"));
-
-        //console.log("Compiling es6 module: " + moduleName + "/" + basename.replace("babylon.", ""));
-
-        var extendsAddition =
-            `var __extends=this&&this.__extends||function(){var t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,o){t.__proto__=o}||function(t,o){for(var n in o)o.hasOwnProperty(n)&&(t[n]=o[n])};return function(o,n){function r(){this.constructor=o}t(o,n),o.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}();
-`;
-
-        var decorateAddition =
-            'var __decorate=this&&this.__decorate||function(e,t,r,c){var o,f=arguments.length,n=f<3?t:null===c?c=Object.getOwnPropertyDescriptor(t,r):c;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,c);else for(var l=e.length-1;l>=0;l--)(o=e[l])&&(n=(f<3?o(n):f>3?o(t,r,n):o(t,r))||n);return f>3&&n&&Object.defineProperty(t,r,n),n};\n';
-
-        let content = file.contents.toString();
-        if (content.indexOf('__extends') === -1 && !dependencyTree.length) {
-            extendsAddition = '';
-        }
-
-        if (content.indexOf('__decorate') === -1) {
-            decorateAddition = '';
-        }
-
-        let dependenciesText = `${extendsAddition}
-${decorateAddition}
-`;
-        //if (moduleName !== 'core') {
-        dependenciesText += `var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-            var BABYLON = globalObject["BABYLON"] || {};
-`;
-        /*} else {
-            dependenciesText += `var BABYLON;
-`;
-        }*/
-
-        let exportsText = '';
-        if (!generateIndex) {
-
-            // process parenting!
-            let parentRegex = /__extends\(([A-Z]\w*), _super\)/g;
-            var match = parentRegex.exec(content);
-            while (match != null) {
-                let extendingClass = match[1];
-                // find the first row
-                let extendedMatcher = new RegExp("}\\([BABYLON\\.]*([A-Z]\\w*)\\)\\);\\n\\s*BABYLON." + extendingClass + " = " + extendingClass + ";");
-
-                let extendedArray = extendedMatcher.exec(content);
-                if (extendedArray) {
-                    let firstRowReg = new RegExp("var " + extendingClass + " = .* \\(function");
-                    content = content.replace(firstRowReg, "var " + extendingClass + " = function");
-
-                    extended = extendedArray[1];
-                    content = content.replace(extendedMatcher, `};
-    var CLS${extendingClass};
-    BABYLON.__${extendingClass} = function() {
-        CLS${extendingClass} = CLS${extendingClass} || ${extendingClass}.call(null, BABYLON.__${extended} && BABYLON.__${extended}() || BABYLON.${extended});
-    }
-    Object.defineProperty(BABYLON, "${extendingClass}", {
-        get: function () {
-            BABYLON.__${extendingClass}();
-            return CLS${extendingClass};
-        },
-        enumerable: true,
-        configurable: true
-    });`);
-                    console.log(extendingClass, extended);
-                } else {
-                    console.log(extendingClass + " is not exported");
-                }
-
-                match = parentRegex.exec(content);
-            }
-
-            let loadedFiles = [];
-            dependencyTree[basename].forEach(function (d, idx) {
-                //if (d.module.indexOf("core") !== -1) return;
-                let name = d.file.split(".").pop();
-
-                if (loadedFiles.indexOf(name) === -1/* && !d.newDec*/) {
-                    let regexp = new RegExp("BABYLON." + d.name);
-                    let match = regexp.exec(content);
-                    if (!match) return;
-                    if (d.main)
-                        dependenciesText += `import {${d.name}} from 'babylonjs/${d.module[0]}/es6/${name}';
-`;
-                    else
-                        exportsText += `import {${d.name}} from 'babylonjs/${d.module[0]}/es6/${name}';
-`;
-                    loadedFiles.push(name);
-                }
-                //dependenciesText += `if(BABYLON !== BABYLON${idx}) __extends(BABYLON, BABYLON${idx});
-            });
-            let exported = [];
-            perFile[basename].declarations.forEach(dec => {
-                if (exported.indexOf(dec) !== -1) return;
-                exported.push(dec);
-                exportsText += `var ${dec} = BABYLON.${dec}; export {${dec}};
-`;
-            });
-            if (shaders) {
-                dependenciesText += `import * as Shaders from "babylonjs/${moduleName}/es6/shaders";
-if(BABYLON.Effect) Object.keys(Shaders).forEach(function(shaderName) {BABYLON.Effect.ShadersStore[shaderName] = Shaders[shaderName]})
-`;
-            }
-            if (shaderIncludes) {
-                dependenciesText += `import * as ShaderIncludes from "babylonjs/${moduleName}/es6/shaderIncludes";
-if(BABYLON.Effect) Object.keys(ShaderIncludes).forEach(function(shaderName) {BABYLON.Effect.IncludesShadersStore[shaderName] = ShaderIncludes[shaderName]})
-`;
-            }
-
-            //if (moduleName === "core") {
-            exportsText += `(function() {
-    //var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-    globalObject["BABYLON"] = globalObject["BABYLON"] || BABYLON;
-})();
-`;
-            //}
-        } else {
-            content = '';
-            let basenames = Object.keys(perFile).filter(basefilename => {
-                return perFile[basefilename].module.indexOf(moduleName) !== -1;
-            });
-
-            basenames.forEach(bname => {
-                let name = bname.split(".").pop();
-                dependenciesText += `export * from "babylonjs/${moduleName}/es6/${name}";
-`;
-            })
-        }
-
-
-
-        /*exportsText += `(function() {
-    globalObject["BABYLON"] = globalObject["BABYLON"] || BABYLON;
-    })();
-`;*/
-
-        /*if (dependencies) {
-            dependencies.forEach(function (d, idx) {
-                if (d === 'core') return;
-                dependenciesText += `import * as ${d} from 'babylonjs/${d}/es6';
-`;
-                //if (idx > 0) {
-                dependenciesText += `__extends(BABYLON, ${d});
-`;
-                //}
-            });
-        }
- 
- 
- 
-        let exportRegex = /BABYLON.([0-9A-Za-z-_]*) = .*;\n/g
- 
-        var match = exportRegex.exec(content);
- 
-        let exportsArray = [];
-        while (match != null) {
-            if (match[1]) {
-                exportsArray.push(match[1])
-            }
-            match = exportRegex.exec(content);
-        }
- 
-        let exportsText = '';
-        if (moduleName === "core") {
-            exportsText = `(function() {
-    var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-    globalObject["BABYLON"] = BABYLON;
-})();
-`
-        }
- 
-        let exportedItems = '';
-        exportsArray.forEach((e, idx) => {
-            if (e.indexOf('.') === -1) {
-                exportedItems += `${idx ? ',' : ''}${e}`
-                exportsText += `var ${e} = BABYLON.${e};
-`
-            }
-        });
- 
-        exportsText += `
-export { ${exportedItems} };`*/
-
-        /*if (moduleName === "core") {
-            exportsText = `(function() {
-var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
-globalObject["BABYLON"] = BABYLON;
-})();
-`*/
-
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-
-        if (file.isStream()) {
-            //streams not supported, no need for now.
-            return;
-        }
-
-        try {
-            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 }));
-        }
-        cb();
-    });
-}

+ 0 - 97
Tools/Gulp/gulp-removeShaderComments.js

@@ -1,97 +0,0 @@
-'use strict';
-
-var through = require('through2');
-var PluginError = require('gulp-util').PluginError;
-var singleComment = 1;
-var multiComment = 2;
-
-function uncomment(str, opts) {
-    opts = opts || {};
-
-    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 gulpUncomment(options) {
-    return main(options, uncomment);
-}
-
-function main(options, func) {
-    return through.obj(function (file, enc, cb) {
-        if (file.isNull()) {
-            cb(null, file);
-            return;
-        }
-        if (file.isStream()) {
-            cb(new PluginError("Remove Shader Comments", "Streaming not supported."));
-        }
-        file.contents = Buffer.from(func(file.contents.toString(), options));
-        this.push(file);
-        return cb();
-    });
-}
-
-module.exports = gulpUncomment;

+ 0 - 747
Tools/Gulp/gulp-validateTypedoc.js

@@ -1,747 +0,0 @@
-'use strict';
-
-var fs = require('fs');
-var Vinyl = require('vinyl');
-var path = require('path');
-var through = require('through2');
-var PluginError = require('plugin-error');
-var supportsColor = require('color-support');
-
-// ______________________________________________ LOGS ______________________________________________
-
-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 currentColor = undefined;
-
-function getTimestamp() {
-    var time = new Date();
-    var timeInString = ("0" + time.getHours()).slice(-2) + ":" +
-        ("0" + time.getMinutes()).slice(-2) + ":" +
-        ("0" + time.getSeconds()).slice(-2);
-
-    if (currentColor) {
-        return white + '[' + currentColor + timeInString + clear + white + ']';
-    }
-    else {
-        return white + '[' + gray + timeInString + white + ']';
-    }
-}
-
-function log() {
-    currentColor = gray;
-    var time = getTimestamp();
-    process.stdout.write(time + ' ');
-    currentColor = undefined;
-
-    console.log.apply(console, arguments);
-    return this;
-}
-
-function warn() {
-    currentColor = yellow;
-    var time = getTimestamp();
-    process.stdout.write(time + ' ');
-    currentColor = undefined;
-
-    console.warn.apply(console, arguments);
-    return this;
-}
-
-function err() {
-    currentColor = red;
-    var time = getTimestamp();
-    process.stderr.write(time + ' ');
-    currentColor = undefined;
-
-    console.error.apply(console, arguments);
-    return this;
-}
-
-function success() {
-    currentColor = green;
-    var time = getTimestamp();
-    process.stdout.write(time + ' ');
-    currentColor = undefined;
-
-    console.log.apply(console, arguments);
-    return this;
-}
-
-// ______________________________________________ VALIDATION ____________________________________________
-
-function unixStylePath(filePath) {
-    return filePath.replace(/\\/g, '/');
-}
-
-function Validate(validationBaselineFileName, namespaceName, validateNamingConvention, generateBaseLine) {
-    this.validationBaselineFileName = validationBaselineFileName;
-    this.namespaceName = namespaceName;
-    this.validateNamingConvention = validateNamingConvention;
-    this.generateBaseLine = generateBaseLine;
-
-    this.previousResults = {};
-    this.results = {
-        errors: 0
-    };
-}
-
-Validate.hasTag = function (node, tagName) {
-    tagName = tagName.trim().toLowerCase();
-
-    if (node.comment && node.comment.tags) {
-        for (var i = 0; i < node.comment.tags.length; i++) {
-            if (node.comment.tags[i].tag === tagName) {
-                return true;
-            }
-        }
-    }
-
-    return false;
-}
-
-Validate.position = function (node) {
-    if (!node.sources) {
-        log(node);
-    }
-    return node.sources[0].fileName + ':' + node.sources[0].line;
-}
-
-Validate.upperCase = new RegExp("^[A-Z_]*$");
-Validate.pascalCase = new RegExp("^[A-Z][a-zA-Z0-9_]*$");
-Validate.camelCase = new RegExp("^[a-z][a-zA-Z0-9_]*$");
-Validate.underscoreCamelCase = new RegExp("^_[a-z][a-zA-Z0-9_]*$");
-Validate.underscorePascalCase = new RegExp("^_[A-Z][a-zA-Z0-9_]*$");
-
-Validate.prototype.errorCallback = function (parent, node, nodeKind, category, type, msg, position) {
-    this.results[this.filePath] = this.results[this.filePath] || { errors: 0 };
-    var results = this.results[this.filePath];
-
-    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;
-
-        if (Array.isArray(previousRootName)) {
-            while (previousRootName.length > 1) {
-                var previousFirst = previousRootName.shift();
-                previousResults = previousResults[previousFirst];
-                if (!previousResults) {
-                    needCheck = false;
-                    break;
-                }
-            }
-            previousRootName = previousRootName.shift();
-        }
-
-        if (needCheck) {
-            var previousNode = previousResults[previousRootName];
-            if (previousNode) {
-                var previousNodeKind = previousNode[nodeKind];
-                if (previousNodeKind) {
-
-                    if (parent) {
-                        previousNode = previousNodeKind[node];
-                    }
-                    else {
-                        previousNode = previousNodeKind;
-                    }
-
-                    if (previousNode) {
-                        var previousCategory = previousNode[category];
-                        if (previousCategory) {
-                            var previousType = previousCategory[type];
-                            if (previousType) {
-                                // Early exit as it was already in the previous build.
-                                return;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Write Error in output JSON.
-    var rootName = parent ? parent : node;
-    var current = results;
-    if (Array.isArray(rootName)) {
-        while (rootName.length > 1) {
-            var first = rootName.shift();
-            current = current[first] = current[first] || {};
-        }
-        rootName = rootName.shift();
-    }
-
-    current = current[rootName] = current[rootName] || {};
-    current = current[nodeKind] = current[nodeKind] || {};
-    if (parent) {
-        current = current[node] = current[node] || {};
-    }
-    current = current[category] = current[category] || {};
-    current = current[type] = true;
-
-    results.errors++;
-
-    if (!this.generateBaseLine) {
-        err(msg, position);
-    }
-}
-
-Validate.prototype.init = function (cb) {
-    var self = this;
-    if (!this.generateBaseLine && fs.existsSync(this.validationBaselineFileName)) {
-        fs.readFile(this.validationBaselineFileName, "utf-8", function (err, data) {
-            self.previousResults = JSON.parse(data);
-            cb();
-        });
-    }
-    else {
-        cb();
-    }
-}
-
-Validate.prototype.add = function (filePath, content) {
-    this.filePath = filePath && unixStylePath(filePath);
-
-    if (!Buffer.isBuffer(content)) {
-        content = Buffer.from(content);
-    }
-
-    var contentString = content.toString();
-    var json = JSON.parse(contentString);
-
-    this.validateTypedoc(json);
-    if (this.results[this.filePath]) {
-        this.results.errors += this.results[this.filePath].errors;
-    }
-}
-
-Validate.prototype.getResults = function () {
-    return this.results;
-}
-
-Validate.prototype.getContents = function () {
-    return Buffer.from(JSON.stringify(this.results));
-}
-
-/**
- * Validate a TypeDoc JSON file
- */
-Validate.prototype.validateTypedoc = function (json) {
-    for (var i = 0; i < json.children.length; i++) {
-        var namespaces = json.children[i].children;
-        this.validateTypedocNamespaces(namespaces);
-    }
-}
-/**
- * Validate namespaces attach to a declaration file from a TypeDoc JSON file
- */
-Validate.prototype.validateTypedocNamespaces = function (namespaces) {
-    var namespace = null;
-
-    // Check for BABYLON namespace
-    for (var child in namespaces) {
-        if (namespaces[child].name === this.namespaceName) {
-            namespace = namespaces[child];
-            break;
-        }
-    }
-
-    // Exit if not BABYLON related.
-    if (!namespace || !namespace.children) {
-        return;
-    }
-
-    // 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;
-
-    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;
-        }
-        isPublic = containerNode.flags.isPublic;
-
-        // Validate naming.
-        this.validateNaming(null, containerNode);
-
-        // Validate Comments.
-        if (isPublic && !this.validateComment(containerNode)) {
-            this.errorCallback(null,
-                containerNode.name,
-                containerNode.kindString,
-                "Comments",
-                "MissingText",
-                "Missing text for " + containerNode.kindString + " : " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(containerNode));
-        }
-
-        children = containerNode.children;
-
-        //Validate Properties
-        if (children) {
-            for (var b in children) {
-                childNode = children[b];
-
-                // Account for undefined access modifiers.
-                if (!childNode.flags.isPublic &&
-                    !childNode.flags.isPrivate &&
-                    !childNode.flags.isProtected) {
-                    childNode.flags.isPublic = true;
-                }
-                isPublic = childNode.flags.isPublic;
-
-                // Validate Naming.
-                this.validateNaming(containerNode, childNode);
-
-                if (isPublic) {
-                    tags = this.validateTags(childNode);
-                    if (tags) {
-                        this.errorCallback(containerNode.name,
-                            childNode.name,
-                            childNode.kindString,
-                            "Tags",
-                            tags,
-                            "Unrecognized tag " + tags + " at " + childNode.name + " (id: " + childNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
-                    }
-                }
-
-                if (!this.validateComment(childNode)) {
-                    //Validate Signatures
-                    signatures = childNode.signatures;
-                    if (signatures) {
-                        for (var c in signatures) {
-                            signatureNode = signatures[c];
-
-                            if (isPublic) {
-                                if (!this.validateComment(signatureNode)) {
-                                    this.errorCallback(containerNode.name,
-                                        signatureNode.name,
-                                        childNode.kindString,
-                                        "Comments",
-                                        "MissingText",
-                                        "Missing text for " + childNode.kindString + " : " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
-                                }
-
-                                tags = this.validateTags(signatureNode);
-                                if (tags) {
-                                    this.errorCallback(containerNode.name,
-                                        signatureNode.name,
-                                        childNode.kindString,
-                                        "Tags",
-                                        tags,
-                                        "Unrecognized tag " + tags + " at " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
-                                }
-
-                                if (signatureNode.type.name !== "void" && signatureNode.comment && !signatureNode.comment.returns) {
-                                    this.errorCallback(containerNode.name,
-                                        signatureNode.name,
-                                        childNode.kindString,
-                                        "Comments",
-                                        "MissingReturn",
-                                        "No Return Comment at " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
-                                }
-
-                                if (signatureNode.type.name === "void" && signatureNode.comment && signatureNode.comment.returns) {
-                                    this.errorCallback(containerNode.name,
-                                        signatureNode.name,
-                                        childNode.kindString,
-                                        "Comments",
-                                        "UselessReturn",
-                                        "No Return Comment Needed at " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
-                                }
-                            }
-
-                            this.validateParameters(containerNode, childNode, signatureNode, signatureNode.parameters, isPublic);
-                        }
-                    } else {
-                        this.errorCallback(containerNode.name,
-                            childNode.name,
-                            childNode.kindString,
-                            "Comments",
-                            "MissingText",
-                            "Missing text for " + childNode.kindString + " : " + childNode.name + " (id: " + childNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
-                    }
-                }
-
-                // this.validateParameters(containerNode, childNode, childNode.parameters, isPublic);
-            }
-        }
-    }
-}
-
-/**
- * Validate that tags are recognized
- */
-Validate.prototype.validateTags = function (node) {
-    var tags;
-    var errorTags = [];
-
-    if (node.comment) {
-
-        tags = node.comment.tags;
-        if (tags) {
-            for (var i = 0; i < tags.length; i++) {
-                var tag = tags[i];
-                var validTags = ["constructor", "throw", "type", "deprecated", "example", "examples", "remark", "see", "remarks", "ignorenaming"]
-                if (validTags.indexOf(tag.tag) === -1) {
-                    errorTags.push(tag.tag);
-                }
-            }
-        }
-
-    }
-
-    return errorTags.join(",");
-}
-
-/**
- * Validate that a JSON node has the correct TypeDoc comments
- */
-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) {
-        return true;
-    }
-
-    // Return true for private properties (dont validate)
-    if ((node.kindString === "Property" || node.kindString === "Object literal") && (node.flags.isPrivate || node.flags.isProtected)) {
-        return true;
-    }
-
-    // Return true for inherited properties
-    if (node.inheritedFrom) {
-        return true;
-    }
-
-    // Return true for overwrited properties
-    if (node.overwrites) {
-        return true;
-    }
-
-    // Check comments.
-    if (node.comment) {
-        if (node.comment.text || node.comment.shortText) {
-            return true;
-        }
-
-        return false;
-    }
-
-    // Return true for inherited properties (need to check signatures)
-    if (node.kindString === "Function") {
-        return true;
-    }
-
-    return false;
-}
-
-/**
- * Validate comments for paramters on a node
- */
-Validate.prototype.validateParameters = function (containerNode, method, signature, parameters, isPublic) {
-    var parametersNode;
-    for (var parameter in parameters) {
-        parametersNode = parameters[parameter];
-
-        if (isPublic && !this.validateComment(parametersNode)) {
-            // throw containerNode.name + " " + method.kindString + " " + method.name + " " + parametersNode.name + " " + parametersNode.kindString;
-            this.errorCallback([containerNode.name, method.kindString, signature.name],
-                parametersNode.name,
-                parametersNode.kindString,
-                "Comments",
-                "MissingText",
-                "Missing text for parameter " + parametersNode.name + " (id: " + parametersNode.id + ") of " + method.name + " (id: " + method.id + ")", Validate.position(method));
-        }
-
-        if (this.validateNamingConvention && !Validate.camelCase.test(parametersNode.name)) {
-            this.errorCallback([containerNode.name, method.kindString, signature.name],
-                parametersNode.name,
-                parametersNode.kindString,
-                "Naming",
-                "NotCamelCase",
-                "Parameter " + parametersNode.name + " should be Camel Case (id: " + method.id + ")", Validate.position(method));
-        }
-    }
-}
-
-/**
- * Validate naming conventions of a node
- */
-Validate.prototype.validateNaming = function (parent, node) {
-    if (!this.validateNamingConvention) {
-        return;
-    }
-
-    // Ignore Naming Tag Check
-    if (Validate.hasTag(node, 'ignoreNaming')) {
-        return;
-    } else {
-        if (node.signatures) {
-            for (var index = 0; index < node.signatures.length; index++) {
-                var signature = node.signatures[index];
-                if (Validate.hasTag(signature, 'ignoreNaming')) {
-                    return;
-                }
-            }
-        }
-    }
-
-    if (node.inheritedFrom) {
-        return;
-    }
-
-    // Internals are not subject to the public visibility policy.
-    if (node.name && node.name.length > 0 && node.name[0] === "_") {
-        return;
-    }
-
-    if ((node.flags.isPrivate || node.flags.isProtected) && node.flags.isStatic) {
-        if (!Validate.underscorePascalCase.test(node.name)) {
-            this.errorCallback(parent ? parent.name : null,
-                node.name,
-                node.kindString,
-                "Naming",
-                "NotUnderscorePascalCase",
-                node.name + " should be Underscore Pascal Case (id: " + node.id + ")", Validate.position(node));
-        }
-    }
-    else if (node.flags.isPrivate || node.flags.isProtected) {
-        if (!Validate.underscoreCamelCase.test(node.name)) {
-            this.errorCallback(parent ? parent.name : null,
-                node.name,
-                node.kindString,
-                "Naming",
-                "NotUnderscoreCamelCase",
-                node.name + " should be Underscore Camel Case (id: " + node.id + ")", Validate.position(node));
-        }
-    }
-    else if (node.flags.isStatic) {
-        if (!Validate.pascalCase.test(node.name)) {
-            this.errorCallback(parent ? parent.name : null,
-                node.name,
-                node.kindString,
-                "Naming",
-                "NotPascalCase",
-                node.name + " should be Pascal Case (id: " + node.id + ")", Validate.position(node));
-        }
-    }
-    else if (node.kindString == "Module") {
-        if (!(Validate.upperCase.test(node.name) || Validate.pascalCase.test(node.name))) {
-            this.errorCallback(parent ? parent.name : null,
-                node.name,
-                node.kindString,
-                "Naming",
-                "NotUpperCase",
-                "Module is not Upper Case or Pascal Case " + node.name + " (id: " + node.id + ")", Validate.position(node));
-        }
-    }
-    else if (node.kindString == "Interface" ||
-        node.kindString == "Class" ||
-        node.kindString == "Enumeration" ||
-        node.kindString == "Enumeration member" ||
-        node.kindString == "Accessor" ||
-        node.kindString == "Type alias") {
-        if (!Validate.pascalCase.test(node.name)) {
-            this.errorCallback(parent ? parent.name : null,
-                node.name,
-                node.kindString,
-                "Naming",
-                "NotPascalCase",
-                node.name + " should be Pascal Case (id: " + node.id + ")", Validate.position(node));
-        }
-    }
-    else if (node.kindString == "Method" ||
-        node.kindString == "Property" ||
-        node.kindString == "Object literal") {
-
-        // Only warn here as special properties such as FOV may be better capitalized 
-        if (!Validate.camelCase.test(node.name)) {
-            this.errorCallback(parent ? parent.name : null,
-                node.name,
-                node.kindString,
-                "Naming",
-                "NotCamelCase",
-                node.name + " should be Camel Case (id: " + node.id + ")", Validate.position(node));
-        }
-    }
-    else if (node.kindString == "Variable") {
-        this.errorCallback(parent ? parent.name : null,
-            node.name,
-            node.kindString,
-            "Naming",
-            "ShouldNotBeLooseVariable",
-            node.name + " should not be a variable (id: " + node.id + ")", Validate.position(node));
-    }
-    else if (node.kindString === "Function") {
-        if (!Validate.camelCase.test(node.name)) {
-            this.errorCallback(parent ? parent.name : null,
-                node.name,
-                node.kindString,
-                "Naming",
-                "NotCamelCase",
-                node.name + " should be Camel Case (id: " + node.id + ")", Validate.position(node));
-        }
-    }
-    else if (node.kindString == "Constructor") {
-        // Do Nothing Here, this is handled through the class name.
-    }
-    else {
-        this.errorCallback(parent ? parent.name : null,
-            node.name,
-            node.kindString,
-            "Naming",
-            "UnknownNamingConvention",
-            "Unknown naming convention for " + node.kindString + " at " + node.name + " (id: " + node.id + ")", Validate.position(node));
-    }
-}
-
-// ______________________________________________ PLUGIN ____________________________________________
-
-// consts
-const PLUGIN_NAME = 'gulp-validateTypedoc';
-
-// plugin level function (dealing with files)
-function gulpValidateTypedoc(validationBaselineFileName, namespaceName, validateNamingConvention, generateBaseLine) {
-
-    if (!validationBaselineFileName) {
-        throw new PluginError(PLUGIN_NAME, 'Missing validation filename!');
-    }
-    if (typeof validationBaselineFileName !== "string") {
-        throw new PluginError(PLUGIN_NAME, 'Validation filename must be a string!');
-    }
-
-    var validate;
-    var latestFile;
-
-    function bufferContents(file, enc, cb) {
-        // ignore empty files
-        if (file.isNull()) {
-            cb();
-            return;
-        }
-
-        // we don't do streams (yet)
-        if (file.isStream()) {
-            this.emit('error', new Error('gulp-validatTypedoc: Streaming not supported'));
-            cb();
-            return;
-        }
-
-        // set latest file if not already set,
-        // or if the current file was modified more recently.
-        latestFile = file;
-
-        // What will happen once all set.
-        var done = function () {
-            // add file to concat instance
-            validate.add(file.relative, file.contents);
-
-            cb();
-        }
-
-        // Do the validation.
-        if (!validate) {
-            validate = new Validate(validationBaselineFileName, namespaceName, validateNamingConvention, generateBaseLine);
-            validate.init(done);
-        }
-        else {
-            done();
-        }
-    }
-
-    function endStream(cb) {
-        // no files passed in, no file goes out
-        if (!latestFile) {
-            var error = new PluginError(PLUGIN_NAME, 'gulp-validatTypedoc: No Baseline found.');
-            this.emit('error', error);
-            cb();
-            return;
-        }
-
-        var results = validate.getResults();
-        var buffer = Buffer.from(JSON.stringify(results, null, 2))
-
-        if (generateBaseLine) {
-            fs.writeFileSync(validationBaselineFileName, buffer || '');
-        }
-
-        var jsFile = new Vinyl({
-            base: null,
-            path: validationBaselineFileName,
-            contents: buffer
-        });
-
-        this.push(jsFile);
-
-        var action = generateBaseLine ? "baseline generation" : "validation";
-        var self = this;
-        var error = function (message) {
-            generateBaseLine ? warn : err;
-            if (generateBaseLine) {
-                warn(message);
-            }
-            else {
-                err(message);
-                var error = new PluginError(PLUGIN_NAME, message);
-                self.emit('error', error);
-            }
-        }
-
-        if (results.errors > 1) {
-            var message = results.errors + " errors have been detected during the " + action + " !";
-            error(message);
-        }
-        else if (results.errors === 1) {
-            var message = "1 error has been detected during the " + action + " !";
-            error(message);
-        }
-        else {
-            var message = "All formatting check passed successfully during the " + action + " !";
-            success(message);
-        }
-
-        cb();
-    }
-
-    return through.obj(bufferContents, endStream);
-};
-
-// exporting the plugin main function
-module.exports = gulpValidateTypedoc;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 53 - 1481
Tools/Gulp/gulpfile.js


+ 113 - 0
Tools/Gulp/helpers/gulp-addModuleExports.js

@@ -0,0 +1,113 @@
+var through = require('through2');
+var PluginError = require('plugin-error');
+
+/**
+ * The parameters for this function has grown during development.
+ * Eventually, this function will need to be reorganized. 
+ */
+//  subModule, extendsRoot, externalUsingBabylon, noBabylonInit
+module.exports = function (varName, config) {
+    return through.obj(function (file, enc, cb) {
+        config = config || {};
+        if (typeof varName === 'string') {
+            varName = {
+                name: varName,
+                module: varName
+            }
+            if (varName.name === 'BABYLON') {
+                varName.module = 'babylonjs';
+            }
+        }
+        if (!config.dependencies) {
+            if (config.subModule || config.extendsRoot) {
+                config.dependencies = [
+                    {
+                        name: "BABYLON",
+                        module: "babylonjs",
+                        optional: false
+                    }
+                ]
+            }
+        }
+
+        function moduleExportAddition(varName) {
+
+            let dependenciesDefinition = `var amdDependencies = [];`;
+            let functionVariables = '';
+            let requireText = '';
+            let amdText = '';
+            let afterInitText = '';
+            if (config.dependencies) {
+                config.dependencies.forEach(dep => {
+                    if (functionVariables) functionVariables += ',';
+                    functionVariables += dep.name;
+                    requireText += `        ${dep.optional ? ' try { ' : ''} ${dep.name} = ${dep.name} || require("${dep.module}"); ${dep.optional ? ' } catch(e) {} ' : ''}
+`;
+                    amdText += `        ${dep.optional ? ' if(require.specified && require.specified("' + dep.module + '"))' : ''} amdDependencies.push("${dep.module}");
+`;
+                    dependenciesDefinition += `
+    var ${dep.name} = root.${dep.name} || this.${dep.name};`;
+                    afterInitText += `  ${dep.name} = ${dep.name} || this.${dep.name};
+`
+                });
+
+            }
+
+            let base = config.subModule ? 'BABYLON' : varName.name;
+
+            return `\n\n(function universalModuleDefinition(root, factory) {
+    ${dependenciesDefinition}
+    if(typeof exports === 'object' && typeof module === 'object') {
+${requireText}
+        module.exports = factory(${functionVariables});
+    } else if(typeof define === 'function' && define.amd) {
+${amdText}
+        define("${varName.module}", amdDependencies, factory);
+    } else if(typeof exports === 'object') {
+${requireText}
+        exports["${varName.module}"] = factory(${functionVariables});
+    } else {
+        root["${base}"]${(config.subModule && !config.extendsRoot) ? '["' + varName.name + '"]' : ''} = factory(${functionVariables});
+    }
+})(this, function(${functionVariables}) {
+${afterInitText}
+${String(file.contents)}
+    ${varName.name === 'BABYLON' || varName.name === 'INSPECTOR' ? `
+var globalObject = (typeof global !== 'undefined') ? global : ((typeof window !== 'undefined') ? window : this);
+globalObject["${varName.name}"] = ${varName.name};
+//backwards compatibility
+if(typeof earcut !== 'undefined') {
+    globalObject["Earcut"] = {
+        earcut: earcut
+    };
+}` : ''}
+
+    return ${base}${(config.subModule && !config.extendsRoot) ? '.' + varName.name : ''};
+});
+`;
+        }
+
+        if (file.isNull()) {
+            cb(null, file);
+            return;
+        }
+
+        if (file.isStream()) {
+            //streams not supported, no need for now.
+            return;
+        }
+
+        try {
+            //if (config.externalUsingBabylon) {
+            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)))));
+            }*/
+            this.push(file);
+        } catch (err) {
+            this.emit('error', new PluginError('gulp-add-module-exports', err, { fileName: file.path }));
+        }
+        cb();
+    });
+};

+ 139 - 0
Tools/Gulp/helpers/gulp-processAmdDeclarationToModule.js

@@ -0,0 +1,139 @@
+// Gulp Tools
+var fs = require("fs");
+
+var processData = function(data, options) {
+    var moduleName = options.moduleName;
+    var entryPoint = options.entryPoint;
+
+    var str = "" + data;
+
+    // Start process by extracting all lines.
+    let lines = str.split('\n');
+
+    // Let's go line by line and check if we have special folder replacements
+    // Replaces declare module '...'; by declare module 'babylonjs/...'; for instance
+    for (let index = 0; index < lines.length; index++) {
+        let line = lines[index];
+
+        // Replace Type Imports
+        var regexTypeImport = /(.*)type ([A-Za-z0-9]*) = import\("(.*)"\)\.(.*);/g;
+        var match = regexTypeImport.exec(line);
+        if (match) {
+            var spaces = match[1]
+            var module = match[3];
+            var type = match[4];
+            line = `${spaces}import { ${type} } from "${module}";`;
+        }
+
+        // Checks if line is about external module
+        var externalModule = false;
+        if (options.externals) {
+            for (let ext in options.externals) {
+                externalModule = line.indexOf(ext) > -1;
+                if (externalModule) {
+                    break;
+                }
+            }
+        }
+        // If not Append Module Name
+        if (!externalModule) {
+            // Declaration
+            line = line.replace(/declare module "/g, `declare module "${moduleName}/`);
+            // From
+            line = line.replace(/ from "/g, ` from "${moduleName}/`);
+            // Module augmentation
+            line = line.replace(/    module "/g, `    module "${moduleName}/`);
+            // Inlined Import
+            line = line.replace(/import\("/g, `import("${moduleName}/`);
+            // Side Effect Import
+            line = line.replace(/import "/g, `import "${moduleName}/`);
+        }
+
+        // Replace Static Readonly declaration for UMD TS Version compat
+        var regexVar = /(.*)readonly (.*) = (.*);/g;
+        match = regexVar.exec(line);
+        if (match) {
+            let spaces = match[1];
+            let name = match[2];
+            let value = match[3];
+            if (value === "true" || value === "false") {
+                line = `${spaces}readonly ${name}: boolean;`;
+            }
+            else if (value.startsWith('"')) {
+                line = `${spaces}readonly ${name}: string;`;    
+            }
+            else {
+                line = `${spaces}readonly ${name}: number;`;
+            }
+        }
+
+        lines[index] = line;
+    }
+
+    // Recreate the file.
+    str = lines.join('\n');
+
+    // !!! Be carefull
+    // Could cause issues if this appears in several import scope
+    // with different aliases.
+    // !!! Be carefull multiline not managed.
+    // Remove unmanaged externals Appears as classMap false in the config.
+    if (options.externals) {
+        for (let ext in options.externals) {
+            // Need to remove the module and dependencies if false.
+            if (options.externals[ext] === false) {
+                // Replace import { foo, bar } from ...
+                const package = ext;
+                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());
+                        });
+                    }
+                    match = babylonRegex.exec(str);
+                }
+                str = str.replace(babylonRegex, '');
+
+                classes.forEach(cls => {
+                    let className = cls;
+                    let alias = cls;
+
+                    // Deal with import { foo as A, bar as B } from ...
+                    if (cls.indexOf(" as ") > -1) {
+                        const tokens = cls.split(" as ");
+                        className = tokens[0];
+                        alias = tokens[1];
+                    }
+
+                    // !!! Be carefull multiline not managed.
+                    const rg = new RegExp(`.*[ <]${alias}[^\\w].*`, "g")
+                    str = str.replace(rg, "");
+                });
+            }
+        }
+
+        // Remove Empty Lines
+        str = str.replace(/^\s*$/gm, "");
+    }
+
+    // Add Entry point.
+    str += `
+declare module "${moduleName}" {
+    export * from "${moduleName}/${entryPoint.replace(/\.\//g,"").replace(".ts", "")}";
+}`;
+
+    return str;
+}
+
+module.exports = function(fileLocation, options, cb) {
+    options = options || { };
+
+    var data = fs.readFileSync(fileLocation);
+
+    newData = processData(data, options);
+
+    fs.writeFileSync(options.output || fileLocation, newData);
+}

+ 42 - 0
Tools/Gulp/helpers/gulp-processImportsToEs6.js

@@ -0,0 +1,42 @@
+// Dependencies.
+var through = require('through2');
+var PluginError = require('plugin-error');
+let fs = require('fs');
+
+/**
+ * Replace all imports by their corresponding ES6 imports.
+ */
+function processImports(sourceCode, replacements) {
+
+    for (let replacement of replacements) {
+        var regex = new RegExp(`(["'])${replacement.packageName}([/"'])`, "g");
+        sourceCode = sourceCode.replace(regex, `$1${replacement.newPackageName}$2`);
+    }
+
+    return sourceCode;
+}
+
+/**
+ * Replaces all imports by their es6 peers.
+ */
+function main(replacements) {
+    return through.obj(function (file, enc, cb) {
+            if (file.isNull()) {
+                cb(null, file);
+                return;
+            }
+            if (file.isStream()) {
+                cb(new PluginError("Process Shader", "Streaming not supported."));
+            }
+
+            let data = file.contents.toString();
+            data = processImports(data, replacements);
+
+            // Go to disk.
+            fs.writeFileSync(file.path, data);
+
+            return cb();
+        });
+}
+
+module.exports = main;

+ 44 - 0
Tools/Gulp/helpers/gulp-processLooseDeclarationsEs6.js

@@ -0,0 +1,44 @@
+// Dependencies.
+var through = require('through2');
+var PluginError = require('plugin-error');
+let fs = require('fs');
+
+/**
+ * Encapsulates types in declare global { }
+ */
+function processLooseDeclarations(sourceCode) {
+    // To replace if that causes issue (defining start point of the concat
+    // as interface like the first code line of the first mixin)
+    sourceCode = sourceCode.replace(/declare /g, "");
+    sourceCode = sourceCode.replace(/interface /, `declare global {
+interface `);
+    sourceCode += `
+}`;
+
+    return sourceCode;
+}
+
+/**
+ * Prepare loose declarations to be added to the package.
+ */
+function main(replacements) {
+    return through.obj(function (file, enc, cb) {
+        if (file.isNull()) {
+            cb(null, file);
+            return;
+        }
+        if (file.isStream()) {
+            cb(new PluginError("Process Shader", "Streaming not supported."));
+        }
+
+        let data = file.contents.toString();
+        data = processLooseDeclarations(data, replacements);
+
+        file.contents = Buffer.from(data);
+        this.push(file);
+
+        return cb();
+    });
+}
+
+module.exports = main;

+ 262 - 0
Tools/Gulp/helpers/gulp-processModuleDeclarationToNamespace.js

@@ -0,0 +1,262 @@
+// Gulp Tools
+var fs = require("fs");
+
+var processData = function(data, packageName, options) {
+    var str = "" + data;
+
+    // Start process by extracting all lines.
+    let lines = str.split('\n');
+
+    // Let's go line by line and check if we have special folder replacements
+    // Replaces declare module 'babylonjs'; by declare module BABYLON for instance
+    for (var index = 0; index < lines.length; index++) {
+        var namespace = options.moduleName;
+        var regex = /declare module ["'](.*)["'] {/g;
+
+        if (options.moduleSpecifics) {
+            var match = regex.exec(lines[index]);
+
+            if (!match) {
+                continue;
+            }
+
+            var module = match[1];
+
+            options.moduleSpecifics.forEach(function(specific) {
+                if (module.indexOf(specific.path) > -1) {
+                    namespace = specific.namespace;
+                }
+            });
+        }
+
+        lines[index] = lines[index].replace(regex, `declare module ${namespace} {`);
+    }
+
+    // Replace module augmentation blocks
+    for (var index = 0; index < lines.length; index++) {
+        var namespace = options.moduleName;
+        var regex = /\smodule ["'](.*)["'] {/g;
+        var match = regex.exec(lines[index]);
+        if (!match) {
+            continue;
+        }
+        lines[index] = "";
+
+        // Find matching closing curly }
+        var opened = 0;
+        for (let endIndex = index; endIndex < lines.length; endIndex++) {
+            let scanLine = lines[endIndex].trim();
+            if (scanLine.length === 0) {
+                continue;
+            }
+            // Skip comments
+            if (scanLine[0] === "*" || scanLine[0] === "/") {
+                continue;
+            }
+
+            // Count open curly
+            if (scanLine.indexOf("{") != -1) {
+                opened++;
+            }
+            // And closing ones
+            if (scanLine.indexOf("}") != -1) {
+                opened--;
+
+                // until the closing module
+                if (opened < 0) {
+                    lines[endIndex] = "";
+                    index = endIndex;
+                    break;
+                }
+            }
+        }
+    }
+
+    // Recreate the file.
+    str = lines.join('\n');
+
+    // First let s deal with internal aliased imports.
+    if (options.moduleSpecifics) {
+        // Find all imported classes and aliased classes.
+        var babylonRegex = new RegExp(`import {(.*)} from ['"](.*)['"];`, "g");
+        var match = babylonRegex.exec(str);
+        let aliasedClasses = new Set();
+        while (match != null) {
+            if (match[1]) {
+                match[1].split(",").forEach(element => {
+                    // Filter only aliased classes
+                    if (element.indexOf(" as ") > -1) {
+                        aliasedClasses.add(element.trim() + " as " + match[2]);
+                    }
+                });
+            }
+            match = babylonRegex.exec(str);
+        }
+        str = str.replace(babylonRegex, '');
+
+        // For every aliased.
+        aliasedClasses.forEach(cls => {
+            const tokens = cls.split(" as ");
+            const className = tokens[0];
+            const alias = tokens[1];
+            const package = tokens[2];
+
+            // Use the default module name.
+            let namespace = options.moduleName;
+            // If they are part of a specific module.
+            options.moduleSpecifics.forEach(function(specific) {
+                if (package.indexOf(specific.path) > -1) {
+                    namespace = specific.namespace;
+                }
+            });
+
+            // Replace
+            const rg = new RegExp(`([ <])(${alias})([^\\w])`, "g")
+            str = str.replace(rg, `$1${namespace}.${className}$3`);
+        });
+    }
+
+    // Let s clean up all the import * from BABYLON or the package itself as we know it is part of
+    // the same namespace... Should be
+    str = str.replace("import * as BABYLON from 'babylonjs';", "");
+    let regexp = new RegExp(`import {(.*)} from ['"]${packageName}(.*)['"];`, 'g');
+    str = str.replace(regexp, '');
+    
+    // Let s clean other chosen imports from the mix.
+    if (options.importsToRemove) {
+        while (options.importsToRemove.length) {
+            let remove = options.importsToRemove.pop();
+            str = str.replace(new RegExp(`import '${remove}';`), '');
+        }
+    }
+
+    // Find all other imported classes (Part of BABYLON or Loaders for instance)
+    // and suffix them by the namespace.
+    if ((options.classMap)) {
+        // Replace import { foo, bar } from ...
+        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());
+                    });
+                }
+                match = babylonRegex.exec(str);
+            }
+            str = str.replace(babylonRegex, '');
+
+            classes.forEach(cls => {
+                let className = cls;
+                let alias = cls;
+
+                // Deal with import { foo as A, bar as B } from ...
+                if (cls.indexOf(" as ") > -1) {
+                    const tokens = cls.split(" as ");
+                    className = tokens[0];
+                    alias = tokens[1];
+                }
+
+                // !!! Be carefull
+                // Could cause issues if this appears in several import scope
+                // with different aliases.
+                // !!! Be carefull multiline not managed.
+                // False is a special case to remove all the lines.
+                if (options.classMap[package] === false) {
+                    const rg = new RegExp(`.*[ <]${alias}[^\\w].*`, "g")
+                    str = str.replace(rg, "");
+                }
+                // Else replace with the namespace prefix.
+                else {
+                    const rg = new RegExp(`([ <])(${alias})([^\\w])`, "g")
+                    str = str.replace(rg, `$1${options.classMap[package]}.${className}$3`);
+                }
+            });
+        });
+
+        // Replace import * as ...
+        Object.keys(options.classMap).forEach(package => {
+            var babylonRegex = new RegExp(`import \\* as (.*) from ['"](${package})['"];`, "g");
+
+            var match = babylonRegex.exec(str);
+            let localNamespace = "";
+            if (match && match[1]) {
+                localNamespace = match[1].trim();
+                str = str.replace(babylonRegex, '');
+
+                let rg = new RegExp(`([ <])(${localNamespace}.)([A-Za-z])`, "g")
+                str = str.replace(rg, `$1${options.classMap[package]}.$3`);
+            }
+        });
+    }
+
+    // Clean up named export.
+    str = str.replace(/export {(.*)};/g, '');
+    // Clean up left import.
+    str = str.replace(/import (.*);/g, "");
+    // Clean up export * from.
+    str = str.split("\n").filter(line => line.trim()).filter(line => line.indexOf("export * from") === -1).join("\n");
+
+    // Remove empty module declaration
+    var cleanEmptyNamespace = function(str, moduleName) {
+        let emptyDeclareRegexp = new RegExp("declare module " + moduleName + " {\\s*}\\s*", "gm");
+        str = str.replace(emptyDeclareRegexp, "");
+
+        return str;
+    }
+    str = cleanEmptyNamespace(str, options.moduleName);
+
+    // Remove empty module declaration of specific modules
+    if (options.moduleSpecifics) {
+        options.moduleSpecifics.forEach(function(specific) {
+            str = cleanEmptyNamespace(str, specific.namespace);
+        });
+    }
+
+    // Remove Empty Lines
+    str = str.replace(/^\s*$/gm, "");
+
+    // Remove Inlined Import
+    str = str.replace(/import\("[A-Za-z0-9\/]*"\)\./g, "");
+
+    return str;
+}
+
+module.exports = function(fileLocation, packageName, options, cb) {
+    options = options || { };
+
+    fs.readFile(fileLocation, function(err, data) {
+        if (err) throw err;
+
+        data += "";
+        // For Raanan, litteral import hack TO BETTER INTEGRATE
+        data = data.replace('import "../sass/main.scss";', "");
+
+        if (options.prependText) {
+            data = options.prependText + '\n' + data.toString();
+        }
+
+        var newData = "";
+        if (options) {
+            newData = processData(data, packageName, options);
+
+            var namespaceData = newData;
+            if (options.prependToNamespaceText) {
+                namespaceData = options.prependToNamespaceText + '\n' + namespaceData;
+            }
+            fs.writeFileSync(fileLocation.replace('.module', ''), namespaceData);
+        }
+
+        if (options.doNotAppendNamespace) {
+            fs.writeFileSync(fileLocation, data);
+        }
+        else {
+            fs.writeFileSync(fileLocation, data + "\n" + newData);
+        }
+
+        cb && cb();
+    });
+}

+ 137 - 0
Tools/Gulp/helpers/gulp-processShaders.js

@@ -0,0 +1,137 @@
+// Dependencies.
+var through = require('through2');
+var PluginError = require('plugin-error');
+let path = require('path');
+let fs = require('fs');
+
+/**
+ * Template creating hidden ts file containing the shaders.
+ */
+let tsShaderTemplate = 
+`import { Effect } from "##EFFECTLOCATION_PLACEHOLDER##";
+##INCLUDES_PLACEHOLDER##
+let name = '##NAME_PLACEHOLDER##';
+let shader = \`##SHADER_PLACEHOLDER##\`;
+
+Effect.##SHADERSTORE_PLACEHOLDER##[name] = shader;
+##EXPORT_PLACEHOLDER##
+`;
+
+
+/**
+ * Get the shaders name from their path.
+ */
+function getShaderName(filename) {
+    let parts = filename.split('.');
+    if (parts[1] !== 'fx') {
+        return parts[0] + (parts[1] === 'fragment' ? 'Pixel' : 'Vertex') + "Shader";
+    } else {
+        return parts[0];
+    }
+}
+
+/**
+ * Get the shaders included in the current one to generate to proper imports.
+ */
+function getIncludes(sourceCode) {
+    var regex = /#include<(.+)>(\((.*)\))*(\[(.*)\])*/g;
+    var match = regex.exec(sourceCode);
+
+    var includes = new Set();
+
+    while (match != null) {
+        let includeFile = match[1];
+
+        // Uniform declaration
+        if (includeFile.indexOf("__decl__") !== -1) {
+            includeFile = includeFile.replace(/__decl__/, "");
+
+            // Add non UBO import
+            const noUBOFile = includeFile + "Declaration";
+            includes.add(noUBOFile);
+
+            includeFile = includeFile.replace(/Vertex/, "Ubo");
+            includeFile = includeFile.replace(/Fragment/, "Ubo");
+            const uBOFile = includeFile + "Declaration";
+            includes.add(uBOFile);
+        }
+        else {
+            includes.add(includeFile);
+        }
+
+        match = regex.exec(sourceCode);
+    }
+
+    return includes;
+}
+
+/**
+ * Generate a ts file per shader file.
+ */
+function main(isCore) {
+    return through.obj(function (file, enc, cb) {
+            if (file.isNull()) {
+                cb(null, file);
+                return;
+            }
+            if (file.isStream()) {
+                cb(new PluginError("Process Shader", "Streaming not supported."));
+            }
+    
+            const filename = path.basename(file.path);
+            const normalized = path.normalize(file.path);
+            const directory = path.dirname(normalized);
+            const shaderName = getShaderName(filename);
+            const tsFilename = filename.replace('.fx', '.ts');
+            let fxData = file.contents.toString();
+
+            // Remove Trailing whitespace...
+            fxData = fxData.replace(/[^\S\r\n]+$/gm, "");
+
+            // Generate imports for includes.
+            let includeText = "";
+            const includes = getIncludes(fxData);
+            includes.forEach((entry) => {
+                if (isCore) {
+                    includeText = includeText + `import "./ShadersInclude/${entry}";
+`;
+                }
+                else {
+                    includeText = includeText + `import "babylonjs/Shaders/ShadersInclude/${entry}";
+`;
+                }
+            });
+
+            // Chose shader store.
+            const isInclude = directory.indexOf("ShadersInclude") > -1;
+            const shaderStore = isInclude ? "IncludesShadersStore" : "ShadersStore";
+            let effectLocation;
+            if (isCore) {
+                if (isInclude) {
+                    effectLocation = "../../Materials/effect";
+                }
+                else {
+                    effectLocation = "../Materials/effect";
+                }
+            }
+            else {
+                effectLocation = "babylonjs/Materials/effect";
+            }
+
+            // Fill template in.
+            let tsContent = tsShaderTemplate.replace('##EFFECTLOCATION_PLACEHOLDER##', effectLocation);
+            tsContent = tsContent.replace('##INCLUDES_PLACEHOLDER##', includeText);
+            tsContent = tsContent.replace('##NAME_PLACEHOLDER##', shaderName);
+            tsContent = tsContent.replace('##SHADER_PLACEHOLDER##', fxData);
+            tsContent = tsContent.replace('##SHADERSTORE_PLACEHOLDER##', shaderStore);
+            tsContent = tsContent.replace('##EXPORT_PLACEHOLDER##', `/** @hidden */
+export var ${shaderName} = { name, shader };`)
+
+            // Go to disk.
+            fs.writeFileSync(directory + '/' + tsFilename, tsContent);
+
+            return cb();
+        });
+}
+
+module.exports = main;

+ 100 - 0
Tools/Gulp/helpers/gulp-remapPaths.js

@@ -0,0 +1,100 @@
+'use strict';
+
+var through = require('through2');
+var path = require('path');
+var fs = require('fs');
+var PluginError = require('plugin-error');
+
+function modifyPath(str, filePath, opts) {
+    opts = opts || {};
+    str += "";
+
+    // Start process by extracting all lines.
+    let lines = str.split('\n');
+
+    // Let's go line by line and replace the imports sources by their resolved locations
+    for (let index = 0; index < lines.length; index++) {
+        let line = lines[index];
+
+        // Replace Static Readonly declaration for UMD TS Version compat
+        var regexVar = /(.*)import .*"(.*)";/g;
+        var match = regexVar.exec(line);
+        if (match) {
+            // Extract the typescript node based import location
+            const location = match[2];
+            let newLocation = location;
+    
+            // Adds file relative path
+            const lastSlash = location.lastIndexOf("/");
+            let pathToTest = location;
+            if (lastSlash > -1) {
+                pathToTest = location.slice(lastSlash + 1);
+            }
+            if (pathToTest.match(/^[A-Z].*/g)) {
+                if (!pathToTest.startsWith("I") || pathToTest === "Instrumentation" || pathToTest === "Inputs") {
+                    newLocation += "/index";
+                }
+            }
+
+            if (!location.startsWith(".")) {
+                const rel = path.relative(filePath, opts.basePath);
+                const count = (rel.match(/..\\/g) || []).length;
+                if (count === 0) {
+                    newLocation = "./" + newLocation;
+                }
+                else {
+                    for (let i = 0; i < count; i++) {
+                        newLocation = "../" + newLocation;
+                    }
+                }
+            }
+    
+            // Replace the location by the new one
+            line = line.replace('"' + location + '"', '"' + newLocation + '"');
+        }
+
+        regexVar = /export \* from "(.*)";/g;
+        match = regexVar.exec(line);
+        if (match) {
+            // Extract the typescript node based import location
+            const location = match[1];
+            let newLocation = location;
+
+            if (location.match(/\.\/[A-Z].*/g)) {
+                if (location[2] !== "I" || location === "./Instrumentation" || location === "./Inputs") {
+                    newLocation += "/index";
+                }
+            }
+
+            // Replace the location by the new one
+            line = line.replace('"' + location + '"', '"' + newLocation + '"');
+        }
+
+        lines[index] = line;
+    }
+
+    // Recreate the file.
+    str = lines.join('\n');
+    return str;
+}
+
+function main(options, func) {
+    return through.obj(function (file, enc, cb) {
+        if (file.isNull()) {
+            cb(null, file);
+            return;
+        }
+        if (file.isStream()) {
+            cb(new PluginError("Modify Import Paths", "Streaming not supported."));
+        }
+        file.contents = Buffer.from(func(file.contents.toString(), file.path, options));
+        this.push(file);
+        return cb();
+    });
+}
+
+function gulpModifyPath(options) {
+    return main(options, modifyPath);
+}
+
+module.exports = gulpModifyPath;

+ 97 - 0
Tools/Gulp/helpers/gulp-removeShaderComments.js

@@ -0,0 +1,97 @@
+'use strict';
+
+var through = require('through2');
+var PluginError = require('plugin-error');
+var singleComment = 1;
+var multiComment = 2;
+
+function uncomment(str, opts) {
+    opts = opts || {};
+
+    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 gulpUncomment(options) {
+    return main(options, uncomment);
+}
+
+function main(options, func) {
+    return through.obj(function (file, enc, cb) {
+        if (file.isNull()) {
+            cb(null, file);
+            return;
+        }
+        if (file.isStream()) {
+            cb(new PluginError("Remove Shader Comments", "Streaming not supported."));
+        }
+        file.contents = Buffer.from(func(file.contents.toString(), options));
+        this.push(file);
+        return cb();
+    });
+}
+
+module.exports = gulpUncomment;

+ 163 - 0
Tools/Gulp/helpers/gulp-validateImports.js

@@ -0,0 +1,163 @@
+// Gulp Tools
+var fs = require("fs");
+var path = require("path");
+var through = require('through2');
+var PluginError = require('plugin-error');
+var colorConsole = require("../../NodeHelpers/colorConsole");
+
+var config = require("../../Config/config");
+
+const indexExlclusion = ["States", "EmitterTypes"];
+
+const mapping = { };
+config.modules.forEach(moduleName => {
+    mapping[config[moduleName].build.umd.packageName] = moduleName;
+});
+
+var validatePath = function(fileLocation, directory, module, lineNumber, errors) {
+    let internalModulePath = path.join(directory, module + ".ts");
+    // Check .ts path.
+    if (!fs.existsSync(internalModulePath)) {
+        let internalModulePath = path.join(directory, module + ".tsx");
+        // Check .tsx path.
+        if (!fs.existsSync(internalModulePath)) {
+            // If not found, check index.ts for legacy and index files.
+            if (fileLocation.indexOf("legacy") > -1 || fileLocation.indexOf("index") > -1) {
+                let internalModulePath = path.join(directory, module, "index.ts");
+                if (!fs.existsSync(internalModulePath)) {
+                    errors.push(`Line ${lineNumber} Export from folder only allowes if index is present. ${module}`);
+                }
+            }
+            else {
+                errors.push(`Line ${lineNumber} Imports ${module} needs to be full path (not from directory) for tree shaking.`);
+            }
+        }
+    }
+
+    if (internalModulePath.indexOf("index.") > -1) {
+        if (fileLocation.indexOf("legacy") === -1) {
+            let excluded = false;
+            for (let exclusion of indexExlclusion) {
+                if (internalModulePath.indexOf(exclusion) > -1) {
+                    excluded = true;
+                    break;
+                }
+            }
+            if (!excluded) {
+                errors.push(`Line ${lineNumber} Imports ${module} should not be from index for tree shaking.`);
+            }
+        }
+    }
+}
+
+var validateImports = function(data, fileLocation, options) {
+    var str = "" + data;
+    var errors = [];
+
+    // Start process by extracting all lines.
+    let lines = str.split('\n');
+
+    // Let's go line by line and check if we have special folder replacements
+    // Replaces declare module '...'; by declare module 'babylonjs/...'; for instance
+    for (let index = 0; index < lines.length; index++) {
+        let line = lines[index];
+        let module = null, externalModule = null;
+
+        // Find Imports.
+        if (line.indexOf("import") > -1) {
+            let regexTypeImport = new RegExp(`import .* from ['"](.*)['"];`, "g");
+            let match = regexTypeImport.exec(line);
+            if (match) {
+                module = match[1];
+            }
+            else {
+                let regexSideEffectImport = new RegExp(`import \\(*['"](.*)['"]\\)*;`, "g");
+                let matchSideEffects = regexSideEffectImport.exec(line);
+                if (matchSideEffects) {
+                    module = matchSideEffects[1];
+                }
+                else {
+                    continue;
+                }
+            }
+
+            // Checks if line is about external module
+            if (options.externals) {
+                for (let ext in options.externals) {
+                    if (line.indexOf(ext) > -1) {
+                        externalModule = ext;
+                        break;
+                    }
+                }
+            }
+
+            // Check if path is correct internal.
+            if (externalModule) {
+                const splitter = module.indexOf("/");
+                const baseModule = module.substring(0, splitter);
+                if (mapping[baseModule]) {
+                    const configName = mapping[baseModule];
+
+                    const directory = config[configName].computed.srcDirectory;
+                    module = module.substring(splitter);
+                    validatePath(fileLocation, directory, module, index + 1, errors);
+                }
+            }
+            else {
+                // Check Relative.
+                if (!module.startsWith(".")) {
+                    errors.push(`Line ${index + 1} Import ${module} needs to be relative.`);
+                }
+                else {
+                    const directory = path.dirname(fileLocation);
+                    validatePath(fileLocation, directory, module, index + 1, errors);
+                }
+            }
+        }
+    }
+
+    return errors;
+}
+
+function gulpValidateImports(options) {
+    var globalErrors = [];
+
+    return through.obj(function (file, enc, cb) {
+        if (file.isNull()) {
+            cb(null, file);
+            return;
+        }
+        if (file.isStream()) {
+            cb(new PluginError("Validate imports", "Streaming not supported."));
+        }
+        
+        let data = file.contents.toString();
+        let result = validateImports(data, file.path, options);
+
+        if (result.length > 0) {
+            for (let error of result) {
+                globalErrors.push({
+                    message: error,
+                    path: file.path
+                });
+            }
+        }
+
+        return cb();
+    }, 
+    function endStream(cb) {
+        if (globalErrors.length > 0) {
+            for (let error of globalErrors) {
+                colorConsole.error(error.message + " " + error.path);
+            }
+            colorConsole.error(`Import validation failed with ${globalErrors.length} errors.`);
+
+            var finalMessage = new PluginError('gulp-validateImports', `gulp-validateImports: ${globalErrors.length} errors found.`);
+            this.emit('error', finalMessage);
+        }
+
+        cb();
+    });
+}
+
+module.exports = gulpValidateImports;

+ 684 - 0
Tools/Gulp/helpers/gulp-validateTypedoc.js

@@ -0,0 +1,684 @@
+'use strict';
+
+var fs = require('fs');
+var Vinyl = require('vinyl');
+var through = require('through2');
+var PluginError = require('plugin-error');
+var nodeColorConsole = require('../../NodeHelpers/colorConsole');
+
+const log = nodeColorConsole.log;
+const warn = nodeColorConsole.warn;
+const err = nodeColorConsole.error;
+const success = nodeColorConsole.success;
+
+// ______________________________________________ VALIDATION ____________________________________________
+
+function unixStylePath(filePath) {
+    return filePath.replace(/\\/g, '/');
+}
+
+function Validate(validationBaselineFileName, namespaceName, validateNamingConvention, generateBaseLine) {
+    this.validationBaselineFileName = validationBaselineFileName;
+    this.namespaceName = namespaceName;
+    this.validateNamingConvention = validateNamingConvention;
+    this.generateBaseLine = generateBaseLine;
+
+    this.previousResults = {};
+    this.results = {
+        errors: 0
+    };
+}
+
+Validate.hasTag = function (node, tagName) {
+    tagName = tagName.trim().toLowerCase();
+
+    if (node.comment && node.comment.tags) {
+        for (var i = 0; i < node.comment.tags.length; i++) {
+            if (node.comment.tags[i].tag === tagName) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+Validate.position = function (node) {
+    if (!node.sources) {
+        log(node);
+    }
+    return node.sources[0].fileName + ':' + node.sources[0].line;
+}
+
+Validate.upperCase = new RegExp("^[A-Z_]*$");
+Validate.pascalCase = new RegExp("^[A-Z][a-zA-Z0-9_]*$");
+Validate.camelCase = new RegExp("^[a-z][a-zA-Z0-9_]*$");
+Validate.underscoreCamelCase = new RegExp("^_[a-z][a-zA-Z0-9_]*$");
+Validate.underscorePascalCase = new RegExp("^_[A-Z][a-zA-Z0-9_]*$");
+
+Validate.prototype.errorCallback = function (parent, node, nodeKind, category, type, msg, position) {
+    this.results[this.filePath] = this.results[this.filePath] || { errors: 0 };
+    var results = this.results[this.filePath];
+
+    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;
+
+        if (Array.isArray(previousRootName)) {
+            while (previousRootName.length > 1) {
+                var previousFirst = previousRootName.shift();
+                previousResults = previousResults[previousFirst];
+                if (!previousResults) {
+                    needCheck = false;
+                    break;
+                }
+            }
+            previousRootName = previousRootName.shift();
+        }
+
+        if (needCheck) {
+            var previousNode = previousResults[previousRootName];
+            if (previousNode) {
+                var previousNodeKind = previousNode[nodeKind];
+                if (previousNodeKind) {
+
+                    if (parent) {
+                        previousNode = previousNodeKind[node];
+                    }
+                    else {
+                        previousNode = previousNodeKind;
+                    }
+
+                    if (previousNode) {
+                        var previousCategory = previousNode[category];
+                        if (previousCategory) {
+                            var previousType = previousCategory[type];
+                            if (previousType) {
+                                // Early exit as it was already in the previous build.
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Write Error in output JSON.
+    var rootName = parent ? parent : node;
+    var current = results;
+    if (Array.isArray(rootName)) {
+        while (rootName.length > 1) {
+            var first = rootName.shift();
+            current = current[first] = current[first] || {};
+        }
+        rootName = rootName.shift();
+    }
+
+    current = current[rootName] = current[rootName] || {};
+    current = current[nodeKind] = current[nodeKind] || {};
+    if (parent) {
+        current = current[node] = current[node] || {};
+    }
+    current = current[category] = current[category] || {};
+    current = current[type] = true;
+
+    results.errors++;
+
+    if (!this.generateBaseLine) {
+        err(msg, position);
+    }
+}
+
+Validate.prototype.init = function (cb) {
+    var self = this;
+    if (!this.generateBaseLine && fs.existsSync(this.validationBaselineFileName)) {
+        fs.readFile(this.validationBaselineFileName, "utf-8", function (err, data) {
+            self.previousResults = JSON.parse(data);
+            cb();
+        });
+    }
+    else {
+        cb();
+    }
+}
+
+Validate.prototype.add = function (filePath, content) {
+    this.filePath = filePath && unixStylePath(filePath);
+
+    if (!Buffer.isBuffer(content)) {
+        content = Buffer.from(content);
+    }
+
+    var contentString = content.toString();
+    var json = JSON.parse(contentString);
+
+    this.validateTypedoc(json);
+    if (this.results[this.filePath]) {
+        this.results.errors += this.results[this.filePath].errors;
+    }
+}
+
+Validate.prototype.getResults = function () {
+    return this.results;
+}
+
+Validate.prototype.getContents = function () {
+    return Buffer.from(JSON.stringify(this.results));
+}
+
+/**
+ * Validate a TypeDoc JSON file
+ */
+Validate.prototype.validateTypedoc = function (json) {
+    for (var i = 0; i < json.children.length; i++) {
+        var namespaces = json.children[i].children;
+        this.validateTypedocNamespaces(namespaces);
+    }
+}
+/**
+ * Validate namespaces attach to a declaration file from a TypeDoc JSON file
+ */
+Validate.prototype.validateTypedocNamespaces = function (namespaces) {
+    var namespace = null;
+
+    // Check for BABYLON namespace
+    for (var child in namespaces) {
+        if (namespaces[child].name === this.namespaceName) {
+            namespace = namespaces[child];
+            break;
+        }
+    }
+
+    // Exit if not BABYLON related.
+    if (!namespace || !namespace.children) {
+        return;
+    }
+
+    // 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;
+
+    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;
+        }
+        isPublic = containerNode.flags.isPublic;
+
+        // Validate naming.
+        this.validateNaming(null, containerNode);
+
+        // Validate Comments.
+        if (isPublic && !this.validateComment(containerNode)) {
+            this.errorCallback(null,
+                containerNode.name,
+                containerNode.kindString,
+                "Comments",
+                "MissingText",
+                "Missing text for " + containerNode.kindString + " : " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(containerNode));
+        }
+
+        children = containerNode.children;
+
+        //Validate Properties
+        if (children) {
+            for (var b in children) {
+                childNode = children[b];
+
+                // Account for undefined access modifiers.
+                if (!childNode.flags.isPublic &&
+                    !childNode.flags.isPrivate &&
+                    !childNode.flags.isProtected) {
+                    childNode.flags.isPublic = true;
+                }
+                isPublic = childNode.flags.isPublic;
+
+                // Validate Naming.
+                this.validateNaming(containerNode, childNode);
+
+                if (isPublic) {
+                    tags = this.validateTags(childNode);
+                    if (tags) {
+                        this.errorCallback(containerNode.name,
+                            childNode.name,
+                            childNode.kindString,
+                            "Tags",
+                            tags,
+                            "Unrecognized tag " + tags + " at " + childNode.name + " (id: " + childNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
+                    }
+                }
+
+                if (!this.validateComment(childNode)) {
+                    //Validate Signatures
+                    signatures = childNode.signatures;
+                    if (signatures) {
+                        for (var c in signatures) {
+                            signatureNode = signatures[c];
+
+                            if (isPublic) {
+                                if (!this.validateComment(signatureNode)) {
+                                    this.errorCallback(containerNode.name,
+                                        signatureNode.name,
+                                        childNode.kindString,
+                                        "Comments",
+                                        "MissingText",
+                                        "Missing text for " + childNode.kindString + " : " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
+                                }
+
+                                tags = this.validateTags(signatureNode);
+                                if (tags) {
+                                    this.errorCallback(containerNode.name,
+                                        signatureNode.name,
+                                        childNode.kindString,
+                                        "Tags",
+                                        tags,
+                                        "Unrecognized tag " + tags + " at " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
+                                }
+
+                                if (signatureNode.type.name !== "void" && signatureNode.comment && !signatureNode.comment.returns) {
+                                    this.errorCallback(containerNode.name,
+                                        signatureNode.name,
+                                        childNode.kindString,
+                                        "Comments",
+                                        "MissingReturn",
+                                        "No Return Comment at " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
+                                }
+
+                                if (signatureNode.type.name === "void" && signatureNode.comment && signatureNode.comment.returns) {
+                                    this.errorCallback(containerNode.name,
+                                        signatureNode.name,
+                                        childNode.kindString,
+                                        "Comments",
+                                        "UselessReturn",
+                                        "No Return Comment Needed at " + signatureNode.name + " (id: " + signatureNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
+                                }
+                            }
+
+                            this.validateParameters(containerNode, childNode, signatureNode, signatureNode.parameters, isPublic);
+                        }
+                    } else {
+                        this.errorCallback(containerNode.name,
+                            childNode.name,
+                            childNode.kindString,
+                            "Comments",
+                            "MissingText",
+                            "Missing text for " + childNode.kindString + " : " + childNode.name + " (id: " + childNode.id + ") in " + containerNode.name + " (id: " + containerNode.id + ")", Validate.position(childNode));
+                    }
+                }
+
+                // this.validateParameters(containerNode, childNode, childNode.parameters, isPublic);
+            }
+        }
+    }
+}
+
+/**
+ * Validate that tags are recognized
+ */
+Validate.prototype.validateTags = function (node) {
+    var tags;
+    var errorTags = [];
+
+    if (node.comment) {
+
+        tags = node.comment.tags;
+        if (tags) {
+            for (var i = 0; i < tags.length; i++) {
+                var tag = tags[i];
+                var validTags = ["constructor", "throw", "type", "deprecated", "example", "examples", "remark", "see", "remarks", "ignorenaming"]
+                if (validTags.indexOf(tag.tag) === -1) {
+                    errorTags.push(tag.tag);
+                }
+            }
+        }
+
+    }
+
+    return errorTags.join(",");
+}
+
+/**
+ * Validate that a JSON node has the correct TypeDoc comments
+ */
+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) {
+        return true;
+    }
+
+    // Return true for private properties (dont validate)
+    if ((node.kindString === "Property" || node.kindString === "Object literal") && (node.flags.isPrivate || node.flags.isProtected)) {
+        return true;
+    }
+
+    // Return true for inherited properties
+    if (node.inheritedFrom) {
+        return true;
+    }
+
+    // Return true for overwrited properties
+    if (node.overwrites) {
+        return true;
+    }
+
+    // Check comments.
+    if (node.comment) {
+        if (node.comment.text || node.comment.shortText) {
+            return true;
+        }
+
+        return false;
+    }
+
+    // Return true for inherited properties (need to check signatures)
+    if (node.kindString === "Function") {
+        return true;
+    }
+
+    return false;
+}
+
+/**
+ * Validate comments for paramters on a node
+ */
+Validate.prototype.validateParameters = function (containerNode, method, signature, parameters, isPublic) {
+    var parametersNode;
+    for (var parameter in parameters) {
+        parametersNode = parameters[parameter];
+
+        if (isPublic && !this.validateComment(parametersNode)) {
+            // throw containerNode.name + " " + method.kindString + " " + method.name + " " + parametersNode.name + " " + parametersNode.kindString;
+            this.errorCallback([containerNode.name, method.kindString, signature.name],
+                parametersNode.name,
+                parametersNode.kindString,
+                "Comments",
+                "MissingText",
+                "Missing text for parameter " + parametersNode.name + " (id: " + parametersNode.id + ") of " + method.name + " (id: " + method.id + ")", Validate.position(method));
+        }
+
+        if (this.validateNamingConvention && !Validate.camelCase.test(parametersNode.name)) {
+            this.errorCallback([containerNode.name, method.kindString, signature.name],
+                parametersNode.name,
+                parametersNode.kindString,
+                "Naming",
+                "NotCamelCase",
+                "Parameter " + parametersNode.name + " should be Camel Case (id: " + method.id + ")", Validate.position(method));
+        }
+    }
+}
+
+/**
+ * Validate naming conventions of a node
+ */
+Validate.prototype.validateNaming = function (parent, node) {
+    if (!this.validateNamingConvention) {
+        return;
+    }
+
+    // Ignore Naming Tag Check
+    if (Validate.hasTag(node, 'ignoreNaming')) {
+        return;
+    } else {
+        if (node.signatures) {
+            for (var index = 0; index < node.signatures.length; index++) {
+                var signature = node.signatures[index];
+                if (Validate.hasTag(signature, 'ignoreNaming')) {
+                    return;
+                }
+            }
+        }
+    }
+
+    if (node.inheritedFrom) {
+        return;
+    }
+
+    // Internals are not subject to the public visibility policy.
+    if (node.name && node.name.length > 0 && node.name[0] === "_") {
+        return;
+    }
+
+    if ((node.flags.isPrivate || node.flags.isProtected) && node.flags.isStatic) {
+        if (!Validate.underscorePascalCase.test(node.name)) {
+            this.errorCallback(parent ? parent.name : null,
+                node.name,
+                node.kindString,
+                "Naming",
+                "NotUnderscorePascalCase",
+                node.name + " should be Underscore Pascal Case (id: " + node.id + ")", Validate.position(node));
+        }
+    }
+    else if (node.flags.isPrivate || node.flags.isProtected) {
+        if (!Validate.underscoreCamelCase.test(node.name)) {
+            this.errorCallback(parent ? parent.name : null,
+                node.name,
+                node.kindString,
+                "Naming",
+                "NotUnderscoreCamelCase",
+                node.name + " should be Underscore Camel Case (id: " + node.id + ")", Validate.position(node));
+        }
+    }
+    else if (node.flags.isStatic) {
+        if (!Validate.pascalCase.test(node.name)) {
+            this.errorCallback(parent ? parent.name : null,
+                node.name,
+                node.kindString,
+                "Naming",
+                "NotPascalCase",
+                node.name + " should be Pascal Case (id: " + node.id + ")", Validate.position(node));
+        }
+    }
+    else if (node.kindString == "Module") {
+        if (!(Validate.upperCase.test(node.name) || Validate.pascalCase.test(node.name))) {
+            this.errorCallback(parent ? parent.name : null,
+                node.name,
+                node.kindString,
+                "Naming",
+                "NotUpperCase",
+                "Module is not Upper Case or Pascal Case " + node.name + " (id: " + node.id + ")", Validate.position(node));
+        }
+    }
+    else if (node.kindString == "Interface" ||
+        node.kindString == "Class" ||
+        node.kindString == "Enumeration" ||
+        node.kindString == "Enumeration member" ||
+        node.kindString == "Accessor" ||
+        node.kindString == "Type alias") {
+        if (!Validate.pascalCase.test(node.name)) {
+            this.errorCallback(parent ? parent.name : null,
+                node.name,
+                node.kindString,
+                "Naming",
+                "NotPascalCase",
+                node.name + " should be Pascal Case (id: " + node.id + ")", Validate.position(node));
+        }
+    }
+    else if (node.kindString == "Method" ||
+        node.kindString == "Property" ||
+        node.kindString == "Object literal") {
+
+        // Only warn here as special properties such as FOV may be better capitalized 
+        if (!Validate.camelCase.test(node.name)) {
+            this.errorCallback(parent ? parent.name : null,
+                node.name,
+                node.kindString,
+                "Naming",
+                "NotCamelCase",
+                node.name + " should be Camel Case (id: " + node.id + ")", Validate.position(node));
+        }
+    }
+    else if (node.kindString == "Variable") {
+        this.errorCallback(parent ? parent.name : null,
+            node.name,
+            node.kindString,
+            "Naming",
+            "ShouldNotBeLooseVariable",
+            node.name + " should not be a variable (id: " + node.id + ")", Validate.position(node));
+    }
+    else if (node.kindString === "Function") {
+        if (!Validate.camelCase.test(node.name)) {
+            this.errorCallback(parent ? parent.name : null,
+                node.name,
+                node.kindString,
+                "Naming",
+                "NotCamelCase",
+                node.name + " should be Camel Case (id: " + node.id + ")", Validate.position(node));
+        }
+    }
+    else if (node.kindString == "Constructor") {
+        // Do Nothing Here, this is handled through the class name.
+    }
+    else {
+        this.errorCallback(parent ? parent.name : null,
+            node.name,
+            node.kindString,
+            "Naming",
+            "UnknownNamingConvention",
+            "Unknown naming convention for " + node.kindString + " at " + node.name + " (id: " + node.id + ")", Validate.position(node));
+    }
+}
+
+// ______________________________________________ PLUGIN ____________________________________________
+
+// consts
+const PLUGIN_NAME = 'gulp-validateTypedoc';
+
+// plugin level function (dealing with files)
+function gulpValidateTypedoc(validationBaselineFileName, namespaceName, validateNamingConvention, generateBaseLine) {
+
+    if (!validationBaselineFileName) {
+        throw new PluginError(PLUGIN_NAME, 'Missing validation filename!');
+    }
+    if (typeof validationBaselineFileName !== "string") {
+        throw new PluginError(PLUGIN_NAME, 'Validation filename must be a string!');
+    }
+
+    var validate;
+    var latestFile;
+
+    function bufferContents(file, enc, cb) {
+        // ignore empty files
+        if (file.isNull()) {
+            cb();
+            return;
+        }
+
+        // we don't do streams (yet)
+        if (file.isStream()) {
+            this.emit('error', new Error('gulp-validatTypedoc: Streaming not supported'));
+            cb();
+            return;
+        }
+
+        // set latest file if not already set,
+        // or if the current file was modified more recently.
+        latestFile = file;
+
+        // What will happen once all set.
+        var done = function () {
+            // add file to concat instance
+            validate.add(file.relative, file.contents);
+
+            cb();
+        }
+
+        // Do the validation.
+        if (!validate) {
+            validate = new Validate(validationBaselineFileName, namespaceName, validateNamingConvention, generateBaseLine);
+            validate.init(done);
+        }
+        else {
+            done();
+        }
+    }
+
+    function endStream(cb) {
+        // no files passed in, no file goes out
+        if (!latestFile) {
+            var error = new PluginError(PLUGIN_NAME, 'gulp-validatTypedoc: No Baseline found.');
+            this.emit('error', error);
+            cb();
+            return;
+        }
+
+        var results = validate.getResults();
+        var buffer = Buffer.from(JSON.stringify(results, null, 2))
+
+        if (generateBaseLine) {
+            fs.writeFileSync(validationBaselineFileName, buffer || '');
+        }
+
+        var jsFile = new Vinyl({
+            base: null,
+            path: validationBaselineFileName,
+            contents: buffer
+        });
+
+        this.push(jsFile);
+
+        var action = generateBaseLine ? "baseline generation" : "validation";
+        var self = this;
+        var error = function (message) {
+            generateBaseLine ? warn : err;
+            if (generateBaseLine) {
+                warn(message);
+            }
+            else {
+                err(message);
+                var error = new PluginError(PLUGIN_NAME, message);
+                self.emit('error', error);
+            }
+        }
+
+        if (results.errors > 1) {
+            var message = results.errors + " errors have been detected during the " + action + " !";
+            error(message);
+        }
+        else if (results.errors === 1) {
+            var message = "1 error has been detected during the " + action + " !";
+            error(message);
+        }
+        else {
+            var message = "All formatting check passed successfully during the " + action + " !";
+            success(message);
+        }
+
+        cb();
+    }
+
+    return through.obj(bufferContents, endStream);
+};
+
+// exporting the plugin main function
+module.exports = gulpValidateTypedoc;

+ 2 - 46
Tools/Gulp/package.json

@@ -8,52 +8,8 @@
     },
     "readme": "https://github.com/BabylonJS/Babylon.js/edit/master/readme.md",
     "license": "(Apache-2.0)",
-    "devDependencies": {
-        "@types/node": "^8.10.22",
-        "chai": "^4.1.2",
-        "color-support": "^1.1.3",
-        "cors": "^2.8.4",
-        "del": "3.0.0",
-        "dts-bundle": "^0.7.3",
-        "gulp": "^4.0.0",
-        "gulp-clean": "^0.4.0",
-        "gulp-clean-ts-extends": "~0.1.1",
-        "gulp-concat": "~2.6.1",
-        "gulp-connect": "^5.6.1",
-        "gulp-content-to-variable": "^0.1.0",
-        "gulp-debug": "^4.0.0",
-        "gulp-expect-file": "^1.0.0",
-        "gulp-filter": "^5.1.0",
-        "gulp-optimize-js": "^1.1.0",
-        "gulp-rename": "^1.4.0",
-        "gulp-replace": "~1.0.0",
-        "gulp-sourcemaps": "~2.6.4",
-        "gulp-tslint": "^8.1.3",
-        "gulp-typedoc": "^2.2.1",
-        "gulp-typescript": "4.0.2",
-        "gulp-uglify": "^3.0.1",
-        "karma": "^3.1.1",
-        "karma-browserstack-launcher": "^1.3.0",
-        "karma-chai": "^0.1.0",
-        "karma-chrome-launcher": "^2.2.0",
-        "karma-firefox-launcher": "^1.1.0",
-        "karma-mocha": "^1.3.0",
-        "karma-phantomjs-launcher": "^1.0.4",
-        "karma-sinon": "^1.0.5",
-        "merge2": "~1.2.2",
-        "minimist": "^1.2.0",
-        "mocha": "^5.2.0",
-        "phantomjs-prebuilt": "^2.1.16",
-        "sinon": "^6.1.4",
-        "through2": "~2.0.3",
-        "ts-loader": "^4.4.2",
-        "tslint": "^5.11.0",
-        "typedoc": "^0.12.0",
-        "typescript": "~3.0.1",
-        "webpack": "^4.16.3",
-        "webpack-stream": "5.0.0"
-    },
     "scripts": {
-        "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"
+        "install": "cd ../../ && npm install && cd Playground/ && npm install && cd ../Viewer && npm install && cd ../Tools/Gulp/",
+        "build": "gulp --max-old-space-size=8192"
     }
 }

+ 0 - 72
Tools/Gulp/processViewerDeclaration.js

@@ -1,72 +0,0 @@
-module.exports = function (data, options) {
-
-    /*
-    {
-        packageName: string,
-        moduleName: string,
-        importsToRemove: Array<string>,
-        classMap
-    }
-    */
-
-    var str = "" + data;
-
-    // this regex is not working on node 6 for some reason:
-    // str = str.replace(/declare module 'babylonjs-viewer\/' {((?!(declare))(.|\n))*\n}/g, '');
-
-    let lines = str.split('\n');
-    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 ${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:
-
-    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());
-                    });
-                }
-                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`);
-            });
-        })
-    }
-
-    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;
-}

+ 2 - 2
Tools/Gulp/profiling.html

@@ -31,8 +31,8 @@ On this page:
 </ol>
 	<form>
         BJS Version for Build: <select id="versions" onchange="readConfigFile()">
-            <option value="https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/Tools/Gulp/config.json">Master</option>
-            <option value="https://raw.githubusercontent.com/BabylonJS/Babylon.js/preview/Tools/Gulp/config.json">Preview</option>
+            <option value="https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/Tools/Config/config.json">Master</option>
+            <option value="https://raw.githubusercontent.com/BabylonJS/Babylon.js/preview/Tools/Config/config.json">Preview</option>
             <option value="./config.json">Current Local Branch (Firefox only)</option>
         </select><br>
 

+ 9 - 49
Tools/Gulp/readme.md

@@ -22,44 +22,27 @@ npm install
 npm update
 ```
 
-### Update config.json if you want to add your own files:
-```
-"extras" : {
-    "files": [
-        "file1.js", "file2.js"
-    ]
-}
-```
-## From the javascript source
-### Build Babylon.js from the javascript files:
+## Build all the distributed files and tests (release build):
 
 ```
 gulp
 ```
-Will be generated :
-- babylon.js
-- babylon.max.js (unminified)
+Will generate all the files of the dist/preview release folder.
 
-## From the typescript source
-### Build Babylon.js from the typescript files:
+## Build all the distributed files without tests (release build):
 
 ```
-gulp typescript
+gulp typescript-libraries
 ```
-Will be generated :
-- babylon.js
-- babylon.d.ts
-- babylon.noworker.js (minified version without collisions workers)
-- babylon.max.js (unminified)
+Will generate all the files of the dist/preview release folder.
 
-Be aware that all js files content will be overwritten.
+## Run all the tests (release build):
 
-### Build Babylon.js when you save a typescript file:
 ```
-gulp watch
+gulp tests-all
 ```
 
-### Run Integrated Web Server and watch for changes:
+## Run Integrated Web Server and watch for changes (dev build):
 ```
 gulp run
 ```
@@ -69,27 +52,4 @@ you can now freely test in the following URLs:
 - [Materials Library](http://localhost:1338/materialsLibrary/index.html)
 - [Postprocess Library](http://localhost:1338/postProcessLibrary/index.html)
 - [Procedural Textures Library](http://localhost:1338/proceduralTexturesLibrary/index.html)
-- [Local Dev Samples](http://localhost:1338/localDev/index.html)
-
-### Compile all the typscript files to their javascript respective files including declaration file
-```
-gulp typescript-compile
-```
-
-Be aware that all js files content will be overwritten.
-
-### Compile all the libraries
-```
-gulp typescript-libraries
-```
-
-Be aware that all js files content will be overwritten.
-
-### Compile all the typscript and the library
-```
-gulp typescript-all
-```
-### Zip individual Blender python files for distribute-able
-```
-gulp zip-blender
-```
+- [Local Dev Samples](http://localhost:1338/localDev/index.html)

+ 75 - 0
Tools/Gulp/tasks/gulpTasks-dependencies.js

@@ -0,0 +1,75 @@
+// Import Dependencies.
+const gulp = require("gulp");
+const path = require("path");
+const depcruise = require('dependency-cruiser');
+const colorConsole = require('../../NodeHelpers/colorConsole');
+
+// Read the full config.
+const config = require("../../Config/config.js");
+
+/*
+ * TsLint all typescript files from the src directory.
+ */
+const dependencies = function(settings, moduleName, cb) {
+    var cruiseResult = depcruise.cruise(
+        [path.relative(path.resolve("./"), settings.computed.mainDirectory)],
+        {
+            validate: true,
+            ruleSet: {
+                forbidden: [{
+                    name: 'no-circular',
+                    comment: 'circular dependencies will make you dizzy',
+                    severity: 'error',
+                    from: {},
+                    to: {
+                        circular: true
+                    }
+                }],
+                options: {
+                    doNotFollow: "node_modules",
+                    tsConfig: {
+                        fileName: settings.computed.tsConfigPath
+                    },
+                    webpackConfig: {
+                        fileName: settings.computed.webpackConfigPath
+                    }
+                }
+            }
+        });
+
+    if (cruiseResult.summary.error > 0) {
+        var errorCount = cruiseResult.summary.error;
+
+        if (errorCount > 0) {
+            colorConsole.error(`New circular dependencies in ${moduleName.cyan}: ${("" + errorCount).red}`);
+            for (let error of cruiseResult.summary.violations) {
+                colorConsole.error(`    From: '${error.from.replace(/\.\.\//g, "").yellow}' To: '${error.to.replace(/\.\.\//g, "").yellow}'`);
+            }
+            process.exit(1);
+        }
+    }
+
+    colorConsole.success("No New circular dependencies.");
+    cb();
+}
+
+/**
+ * Dynamic module linting for external library (mat, post processes, ...).
+ */
+config.lintModules.map(function(module) {
+    // Task will be like moduleName-circularDependencies
+    gulp.task(module + "-circularDependencies", function(cb) {
+        var settings = config[module];
+
+        dependencies(settings, module, cb);
+    });
+});
+
+/**
+ * Full Librairies tsLint.
+ */
+gulp.task("circularDependencies",
+    gulp.series(config.lintModules.map((module) => {
+        return module + "-circularDependencies";
+    })
+));

+ 64 - 0
Tools/Gulp/tasks/gulpTasks-importLint.js

@@ -0,0 +1,64 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var filter = require('gulp-filter');
+
+// Helpers.
+var validateImports = require("../helpers/gulp-validateImports");
+var uncommentShaders = require('../helpers/gulp-removeShaderComments');
+var processShaders = require("../helpers/gulp-processShaders");
+
+// Read the full config.
+var config = require("../../Config/config.js");
+
+/**
+ * Create shader ts files.
+ */
+var buildShaders = function(settings) {
+    return gulp.src(settings.computed.shaderGlob)
+            .pipe(uncommentShaders())
+            .pipe(processShaders(settings.isCore));
+}
+
+/*
+ * ImportLint all typescript files from the src directory.
+ */
+var importLintLibrary = function(settings) {
+    const fxFilter = filter(['**', '!**/*.fragment.ts', '!**/*.vertex.ts', '!**/ShadersInclude/**'], { restore: false });
+    return gulp.src(settings.computed.tsGlob)
+        .pipe(fxFilter)
+        .pipe(validateImports({
+            externals: settings.build.umd.processDeclaration.classMap
+        }));
+}
+
+/**
+ * Dynamic module linting for library (mat, post processes, ...).
+ */
+var lintLibrary = function(settings) {
+    var tasks = [];
+
+    var shaders = function() { return buildShaders(settings); };
+    var lint = function() { return importLintLibrary(settings); };
+
+    tasks.push(shaders, lint);
+
+    return gulp.series.apply(this, tasks);
+};
+
+/**
+ * Dynamic module linting for library (mat, post processes, ...).
+ */
+config.lintModules.map(function(module) {
+    const settings = config[module];
+    gulp.task(module + "-importLint", lintLibrary(settings));
+});
+
+
+/**
+ * Full Librairies importLint.
+ */
+gulp.task("typescript-libraries-importLint",
+    gulp.series(config.lintModules.map((module) => {
+        return module + "-importLint";
+    })
+));

+ 21 - 0
Tools/Gulp/tasks/gulpTasks-intellisense.js

@@ -0,0 +1,21 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var concat = require("gulp-concat");
+var replace = require("gulp-replace");
+
+// Read the full config.
+var config = require("../../Config/config.json");
+
+/**
+ * Process the .d.ts files or Playground intellisense.
+ */
+gulp.task("intellisense", function() {
+    return gulp.src(config.build.intellisenseSources)
+        .pipe(concat(config.build.intellisenseFile))
+        .pipe(replace(/^\s*readonly _/gm, "protected readonly _"))
+        .pipe(replace(/^\s*static _/gm, "private static _"))
+        .pipe(replace(/^\s*class _/gm, "private class _"))
+        .pipe(replace(/^\s* _/gm, ""))
+        .pipe(replace(/^\s*_/gm, "private _"))
+        .pipe(gulp.dest(config.build.playgroundDirectory));
+});

+ 184 - 0
Tools/Gulp/tasks/gulpTasks-libraries.js

@@ -0,0 +1,184 @@
+// Gulp Tools
+var gulp = require("gulp");
+var webpack = require('webpack');
+var webpackStream = require("webpack-stream");
+var cp = require('child_process');
+var path = require("path");
+var concat = require('gulp-concat');
+var minimist = require("minimist");
+
+// Gulp Helpers
+var uncommentShaders = require('../helpers/gulp-removeShaderComments');
+var processShaders = require("../helpers/gulp-processShaders");
+var processAmdDeclarationToModule = require('../helpers/gulp-processAmdDeclarationToModule');
+var processModuleDeclarationToNamespace = require('../helpers/gulp-processModuleDeclarationToNamespace');
+var del = require("del");
+
+// Parse Command Line.
+var commandLineOptions = minimist(process.argv.slice(2), {
+    boolean: ["noNamespace"],
+    string: ["moduleName"]
+});
+
+// Import Build Config
+var config = require("../../Config/config.js");
+
+/**
+ * Clean shader ts files.
+ */
+var cleanShaders = function(settings) {
+    return del(settings.computed.shaderTSGlob, { force: true });
+}
+
+/**
+ * Create shader ts files.
+ */
+var buildShaders = function(settings) {
+    return gulp.src(settings.computed.shaderGlob)
+            .pipe(uncommentShaders())
+            .pipe(processShaders(settings.isCore));
+}
+
+/**
+ * Build a single library (one of the material of mat lib) from a module (materialsLibrary for instance)
+ */
+var buildExternalLibrariesMultiEntry = function(libraries, settings, isMin) {
+    // Convert Module to Namespace for globals
+    var outputDirectory = settings.computed.distDirectory;
+
+    // Does name contain .min. for min files.
+    var isMinOutputName = libraries[0].output.indexOf(".min.") > -1;
+
+    // Webpack Config.
+    var wpConfig = require(settings.computed.webpackConfigPath);
+
+    // Create multi entry list.
+    wpConfig.entry = { };
+    for (let library of settings.libraries) {
+        let name = library.output.replace(isMinOutputName ? ".min.js" : ".js", "");
+        wpConfig.entry[name] = library.computed.entryPath;
+    }
+
+    // Create output by type (min vs max).
+    if (isMin) {
+        delete wpConfig.devtool;
+        wpConfig.output.filename = isMinOutputName ? '[name].min.js' : '[name].js';
+    }
+    else {
+        // Map Output
+        wpConfig.devtool = "source-map";
+        wpConfig.output.devtoolModuleFilenameTemplate = (info) => {
+            info.resourcePath = path.normalize(info.resourcePath);
+
+            if (!path.isAbsolute(info.resourcePath)) {
+                info.resourcePath = path.join(settings.computed.srcDirectory, info.resourcePath);
+            }
+
+            return `webpack://BABYLONJS/${path.relative(config.computed.rootFolder, info.resourcePath).replace(/\\/g, "/")}`;
+        };
+
+        // Generate unminified file.
+        wpConfig.mode = "development";
+        wpConfig.output.filename = isMinOutputName ? '[name].js' : '[name].max.js';
+    }
+
+    // Generate minified file.
+    let wpBuild = webpackStream(wpConfig, webpack);
+    return wpBuild.pipe(gulp.dest(outputDirectory));
+}
+
+/**
+ * Build AMD DTS Files
+ */
+var buildAMDDTSFiles = function(libraries, settings, cb) {
+    // TODO. Generate all d.ts
+    let library = libraries[0];
+    if (!library.preventLoadLibrary) {
+        // Generate DTS the old way...
+        cp.execSync(`tsc --module amd --outFile "${config.computed.tempTypingsAMDFilePath}" --emitDeclarationOnly true`, {
+            cwd: settings.computed.srcDirectory
+        });
+    }
+    cb();
+}
+
+/**
+ * Append Lose DTS Files allowing isolated Modules build
+ */
+var appendLoseDTSFiles = function(settings) {
+    if (settings.build.loseDTSFiles) {
+        return gulp.src([config.computed.tempTypingsFilePath, path.join(settings.computed.srcDirectory, settings.build.loseDTSFiles.glob)])
+            .pipe(concat(config.computed.tempTypingsFileName))
+            .pipe(gulp.dest(config.computed.tempFolder));
+    }
+    return Promise.resolve();
+}
+
+/**
+ * Process DTS Files
+ */
+var processDTSFiles = function(libraries, settings, cb) {
+    // Convert Module to Namespace for globals
+    var outputDirectory = settings.computed.distDirectory;
+
+    // TODO. Generate all d.ts
+    let library = libraries[0];
+    if (!library.preventLoadLibrary) {
+        // Find declaration path.
+        let fileLocation = path.join(outputDirectory, settings.build.umd.processDeclaration.filename);
+
+        // Convert the tsc AMD BUNDLED declaration to our expected one
+        processAmdDeclarationToModule(config.computed.tempTypingsFilePath, {
+            output: fileLocation,
+            moduleName: commandLineOptions.moduleName || settings.build.umd.packageName,
+            entryPoint: library.entry,
+            externals: settings.build.umd.processDeclaration.classMap,
+        });
+
+        // Convert Module to Namespace for globals
+        if (!commandLineOptions.noNamespace) {
+            processModuleDeclarationToNamespace(fileLocation, settings.build.umd.packageName, settings.build.umd.processDeclaration);
+        }
+    }
+    cb();
+}
+
+/**
+ * Dynamic module creation In Serie for WebPack leaks.
+ */
+function buildExternalLibraries(settings) {
+    // Creates the required tasks.
+    var tasks = [];
+
+    var cleanup = function() { return cleanShaders(settings); };
+    var shaders = function() { return buildShaders(settings); };
+    var buildMin = function() { return buildExternalLibrariesMultiEntry(settings.libraries, settings, true) };
+    var buildMax = function() { return buildExternalLibrariesMultiEntry(settings.libraries, settings, false) };
+
+    var buildAMDDTS = function(cb) { return buildAMDDTSFiles(settings.libraries, settings, cb) };
+    var appendLoseDTS = function() { return appendLoseDTSFiles(settings) };
+    var processDTS = function(cb) { return processDTSFiles(settings.libraries, settings, cb) };
+
+    tasks.push(cleanup, shaders, buildMin, buildMax, buildAMDDTS, appendLoseDTS, processDTS);
+
+    return gulp.series.apply(this, tasks);
+}
+
+/**
+ * Dynamic module creation.
+ */
+config.modules.map(function(module) {
+    const settings = config[module];
+    gulp.task(module, buildExternalLibraries(settings));
+});
+
+/**
+ * Build the releasable files.
+ * Back Compat Only, now name core as it is a lib
+ */
+gulp.task("typescript", gulp.series("core"));
+
+/**
+ * Build all libs.
+ */
+gulp.task("typescript-libraries", gulp.series(config.modules, config.viewerModules));

+ 296 - 0
Tools/Gulp/tasks/gulpTasks-librariesES6.js

@@ -0,0 +1,296 @@
+// Gulp Tools
+var gulp = require("gulp");
+var path = require("path");
+var fs = require("fs-extra");
+var shelljs = require("shelljs");
+var concat = require('gulp-concat');
+
+// Gulp Helpers
+var rmDir = require("../../NodeHelpers/rmDir");
+var processImports = require("../helpers/gulp-processImportsToEs6");
+var processLooseDeclarations = require("../helpers/gulp-processLooseDeclarationsEs6");
+var uncommentShaders = require('../helpers/gulp-removeShaderComments');
+var processShaders = require("../helpers/gulp-processShaders");
+var del = require("del");
+
+// Import Build Config
+var config = require("../../Config/config.js");
+
+/**
+ * Clean Source And Dist folders.
+ */
+var cleanSourceAndDist = function(settings, cb) {
+    rmDir(settings.computed.sourceES6Directory);
+    rmDir(settings.computed.distES6Directory);
+    cb();
+}
+
+/**
+ * Clean shader ts files.
+ */
+var cleanShaders = function(settings) {
+    return del(settings.computed.shaderTSGlob, { force: true });
+}
+
+/**
+ * Create shader ts files.
+ */
+var buildShaders = function(settings) {
+    return gulp.src(settings.computed.shaderGlob)
+            .pipe(uncommentShaders())
+            .pipe(processShaders(settings.isCore));
+}
+
+/**
+ * Copy Sources.
+ */
+var source = function(settings) {
+    return gulp.src(settings.computed.mainDirectory + "/**/*")
+        .pipe(gulp.dest(settings.computed.sourceES6Directory));
+}
+
+/**
+ * Copy dependencies.
+ */
+var dep = function(settings) {
+    const copyPaths = []
+    // Add tsconfig rules.
+    copyPaths.push(path.join(config.computed.rootFolder, "tsconfigRules.json"));
+
+    const tsconfig = require(settings.computed.tsConfigPath);
+    for (let pathName in tsconfig.compilerOptions.paths) {
+        let paths = tsconfig.compilerOptions.paths[pathName];
+        for (let dep of paths) {
+            const fullPath = path.resolve(settings.computed.mainDirectory, 
+                tsconfig.compilerOptions.baseUrl, 
+                dep);
+            copyPaths.push(fullPath);
+        }
+    }
+
+    if (settings.build.es6.webpackBuild && settings.build.es6.webpackBuild.dependencies) {
+        for (let pathName of settings.build.es6.webpackBuild.dependencies) {
+            const dependencyPath = path.join(config.computed.rootFolder, pathName);
+            copyPaths.push(dependencyPath);
+        }
+    }
+
+    return gulp.src(copyPaths, { base: config.computed.rootFolder })
+        .pipe(gulp.dest(config.computed.sourceES6Folder));
+}
+
+/**
+ * Adapt Sources import paths.
+ */
+var modifySources = function(settings) {
+    const tsconfig = require(settings.computed.tsConfigPath);
+
+    var replacements = [];
+    for (let pathName in tsconfig.compilerOptions.paths) {
+        if (pathName.endsWith("/*")) {
+            pathName = pathName.replace("/*", "");
+        }
+
+        for (var moduleName of config.modules) {
+            var module = config[moduleName];
+            if (module.build.umd.packageName === pathName) {
+                if (module.build.es6.packageName) {
+                    var packageName = pathName;
+                    var newPackageName = module.build.es6.packageName;
+                    replacements.push({ 
+                        packageName,
+                        newPackageName
+                    });
+                    break;
+                }
+            }
+        }
+    }
+
+    return gulp.src([settings.computed.sourceES6Directory + "/**/*.ts", 
+        settings.computed.sourceES6Directory + "/**/*.tsx"])
+        .pipe(processImports(replacements));
+}
+
+/**
+ * Adapt TS Config Paths.
+ */
+var modifyTsConfig = function(settings, cb) {
+    const tsconfig = require(settings.computed.tsConfigPath);
+
+    var newPaths = { };
+    for (let pathName in tsconfig.compilerOptions.paths) {
+        var newPathName = pathName;
+        var originalPath = pathName;
+        if (pathName.endsWith("/*")) {
+            pathName = pathName.replace("/*", "");
+        }
+
+        var mapped = false;
+        for (var moduleName of config.modules) {
+            var module = config[moduleName];
+            if (module.build.umd.packageName === pathName) {
+                if (module.build.es6.packageName) {
+                    newPathName = module.build.es6.packageName + "*";
+                    newPaths[newPathName] = [ module.computed.distES6Directory.replace(/\\/g, "/") ];
+                    mapped = true;
+                    break;
+                }
+            }
+        }
+        if (!mapped) {
+            newPaths[newPathName] = tsconfig.compilerOptions.paths[originalPath];
+        }
+    }
+
+    tsconfig.compilerOptions.paths = newPaths;
+
+    const destTsConfig = path.join(settings.computed.sourceES6Directory, "tsconfig.json");
+    fs.writeJSONSync(destTsConfig, tsconfig);
+
+    cb();
+}
+
+/**
+ * Concat Lose DTS Files allowing isolated Modules build
+ */
+var concatLoseDTSFiles = function(settings) {
+    if (settings.build.loseDTSFiles) {
+        return gulp.src([path.join(settings.computed.srcDirectory, settings.build.loseDTSFiles.glob)])
+            .pipe(concat(config.computed.tempTypingsFileName))
+            .pipe(processLooseDeclarations())
+            .pipe(gulp.dest(config.computed.tempFolder));
+    }
+    return Promise.resolve();
+}
+
+/**
+ * Append Lose DTS Files allowing isolated Modules build
+ */
+var appendLoseDTSFiles = function(settings) {
+    if (settings.build.loseDTSFiles) {
+        const mainDeclarationFile = path.join(settings.computed.distES6Directory, settings.build.loseDTSFiles.destFileES6 || "index.d.ts");
+        return gulp.src([mainDeclarationFile, config.computed.tempTypingsFilePath])
+            .pipe(concat(settings.build.loseDTSFiles.destFileES6))
+            .pipe(gulp.dest(settings.computed.distES6Directory));
+    }
+    return Promise.resolve();
+}
+
+/**
+ * TSC Build.
+ */
+var build = function(settings, cb) {
+    // Launch TSC.
+    const options = {
+        cwd: settings.computed.sourceES6Directory,
+        verbose: true
+    };
+
+    let command = `tsc --inlineSources --sourceMap true -t es5 -m esNext --outDir "${settings.computed.distES6Directory}"`;
+    shelljs.exec(command, options, function(code, stdout, stderr) {
+        if (stderr) {
+            console.log(stderr);
+        }
+        if (stdout) {
+            console.log(stdout);
+        }
+
+        if (code !== 0) {
+            cb("TSC Failed.")
+        }
+        else {
+            cb();
+        }
+    });
+}
+
+/**
+ * Webpack Build.
+ */
+var buildWebpack = function(settings, module, cb) {
+    const gulpPath = path.join(config.computed.sourceES6Folder, "Tools/Gulp");
+    // Launch TSC.
+    const options = {
+        cwd: gulpPath,
+        verbose: true
+    };
+
+    let command = `gulp ${module} --noNamespace --moduleName ${settings.build.es6.packageName}`;
+    shelljs.exec(command, options, function(code, stdout, stderr) {
+        if (stderr) {
+            console.log(stderr);
+        }
+        if (stdout) {
+            console.log(stdout);
+        }
+
+        if (code !== 0) {
+            cb("Webpack Build Failed.")
+        }
+        else {
+            cb();
+        }
+    });
+}
+
+/**
+ * Copy Webpack Dist.
+ */
+var copyWebpackDist = function(settings, module) {
+    var es6Config = require(path.join(config.computed.sourceES6Folder, "Tools/Config/config"));
+
+    return gulp.src(es6Config[module].computed.distDirectory + "/**/*")
+        .pipe(gulp.dest(settings.computed.distES6Directory));
+}
+
+/**
+ * Dynamic es 6 module creation.
+ */
+function buildES6Library(settings, module) {
+    // Creates the required tasks.
+    var tasks = [];
+
+    var cleanTasks = [
+        function cleanES6(cb) { return cleanSourceAndDist(settings, cb); },
+        function cleanES6Shaders() { return cleanShaders(settings); }
+    ];
+    var shaders = function() { return buildShaders(settings); };
+    var copySource = function() { return source(settings); };
+    var dependencies = function() { return dep(settings); };
+    var adaptSourceImportPaths = function() { return modifySources(settings); };
+    var adaptTsConfigImportPaths = function(cb) { return modifyTsConfig(settings, cb); };
+
+    // Build with ts or webpack
+    var buildSteps = null;
+    if (settings.build.es6.webpackBuild) {
+        buildSteps = [
+            function buildes6(cb) { return buildWebpack(settings, module, cb) },
+            function copyDist() { return copyWebpackDist(settings, module) }
+        ];
+    }
+    else {
+        buildSteps = [
+            function buildes6(cb) { return build(settings, cb) }, 
+            function concatLoseDTS() { return concatLoseDTSFiles(settings) },
+            function appendLoseDTS() { return appendLoseDTSFiles(settings) }
+        ];
+    }
+
+    tasks.push(...cleanTasks, shaders, copySource, dependencies, adaptSourceImportPaths, adaptTsConfigImportPaths, ...buildSteps);
+
+    return gulp.series.apply(this, tasks);
+}
+
+/**
+ * Dynamic es 6 module creation.
+ */
+config.modules.map(function(module) {
+    const settings = config[module];
+    gulp.task(module + "-es6", buildES6Library(settings, module));
+});
+
+/**
+ * Build all es 6 libs.
+ */
+gulp.task("typescript-es6", gulp.series(config.modules.map((module) => module + "-es6")));

+ 48 - 0
Tools/Gulp/tasks/gulpTasks-localRun.js

@@ -0,0 +1,48 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var connect = require("gulp-connect");
+var minimist = require("minimist");
+var fs = require('fs');
+var path = require('path');
+
+// Read the full config.
+var config = require("../../Config/config.json");
+
+// Comand line parsing.
+var commandLineOptions = minimist(process.argv.slice(2), {
+    boolean: ["public"]
+});
+
+// Skip known extensions.
+var skipExtensions = [".js", ".glb", ".gltf", ".bin", ".html", ".gif", ".jpg", ".jpeg", ".png", ".dds", ".babylon", "ktx", ".map"];
+
+/**
+ * Embedded webserver for test convenience.
+ */
+gulp.task("webserver", function() {
+    var rootRelativePath = "../../";
+    var options = {
+        root: rootRelativePath,
+        port: 1338,
+        livereload: false,
+        middleware: function(connect, opt) {
+            return [function (req, res, next) {
+                var extension = path.extname(decodeURIComponent(req.originalUrl));
+                if (req.originalUrl.indexOf(config.build.localDevES6FolderName) > -1 && skipExtensions.indexOf(extension) === -1) {
+                    // Append .js for es6 modules.
+                    if (!fs.existsSync(rootRelativePath + req.originalUrl)) {
+                        req.url += ".js";
+                    }
+                }
+                next();
+              }
+            ]
+        }
+    };
+
+    if (commandLineOptions.public) {
+        options.host = "0.0.0.0";
+    }
+
+    connect.server(options);
+});

+ 16 - 0
Tools/Gulp/tasks/gulpTasks-netlify.js

@@ -0,0 +1,16 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var del = require("del");
+
+// Cleanup Netlify folder before deploy.
+gulp.task("netlify-cleanup", function() {
+    //set by netlify
+    if (process.env.REPOSITORY_URL) {
+        return del([
+            "../../../Viewer/node_modules/**/*"
+        ], { force: true });
+    }
+    else {
+        return Promise.resolve();
+    }
+})

+ 33 - 0
Tools/Gulp/tasks/gulpTasks-npmPackages.js

@@ -0,0 +1,33 @@
+// Import Dependencies.
+var gulp = require("gulp");
+
+// Read the full config.
+var publish = require("../../Publisher/tasks/main");
+
+/**
+ * Get Ready to test Npm Packages.
+ */
+gulp.task("npmPackages-es6", gulp.series("typescript-es6", function(cb) {
+    publish(false, {
+        es6: true
+    });
+    cb();
+}));
+
+/**
+ * Get Ready to test Npm Packages.
+ */
+gulp.task("npmPackages-UMD", gulp.series("typescript-libraries", function(cb) {
+    publish(false, {
+        umd: true
+    });
+    cb();
+}));
+
+/**
+ * Get Ready to test Npm Packages.
+ */
+gulp.task("npmPackages-all", gulp.series("typescript-libraries", "typescript-es6", function(cb) {
+    publish(false);
+    cb();
+}));

+ 22 - 0
Tools/Gulp/tasks/gulpTasks-remapPaths.js

@@ -0,0 +1,22 @@
+// Gulp Tools
+var gulp = require("gulp");
+var minimist = require("minimist");
+
+// Helpers
+var remapPaths = require("../helpers/gulp-remapPaths");
+
+// Parse Command Line.
+var commandLineOptions = minimist(process.argv.slice(2), {
+    string: ["path"]
+});
+
+/**
+ * This tasks remaps all the import path of a typescript project to their relative paths.
+ */
+gulp.task("remapPaths", function() {
+    const path = commandLineOptions.path;
+
+    return gulp.src(path + "/**/*.ts", { base: path })
+        .pipe(remapPaths({ basePath: path }))
+        .pipe(gulp.dest(path));
+});

+ 324 - 0
Tools/Gulp/tasks/gulpTasks-tests.js

@@ -0,0 +1,324 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var typescript = require("gulp-typescript");
+var fs = require("fs");
+var karmaServer = require('karma').Server;
+var webpack = require('webpack');
+var webpackStream = require("webpack-stream");
+var rename = require("gulp-rename");
+
+// Import Helpers.
+var rmDir = require("../../NodeHelpers/rmDir");
+
+// Read the full config.
+var config = require("../../Config/config.json");
+var relativeRootDir = "../../../";
+var rootDir = __dirname + "/" + relativeRootDir;
+
+/**
+ * Launches the KARMA validation tests in chrome in order to debug them.
+ */
+gulp.task("tests-validation-karma", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "tests/validation/karma.conf.js",
+        singleRun: false
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+});
+
+/**
+ * Launches the KARMA validation tests in ff or virtual screen ff on travis for a quick analysis during the build.
+ */
+gulp.task("tests-validation-virtualscreen", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "tests/validation/karma.conf.js",
+        singleRun: true,
+        browsers: ['Firefox']
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+});
+
+/**
+ * Launches the KARMA validation tests in browser stack for remote and cross devices validation tests.
+ */
+gulp.task("tests-validation-browserstack", function(done) {
+    if (!process.env.BROWSER_STACK_USERNAME) {
+        done();
+        return;
+    }
+
+    var kamaServerOptions = {
+        configFile: rootDir + "tests/validation/karma.conf.browserstack.js",
+        singleRun: true
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+});
+
+/**
+ * Transpiles typescript unit tests. 
+ */
+gulp.task("tests-unit-transpile", function(done) {
+    var tsProject = typescript.createProject(rootDir + "tests/unit/tsconfig.json");
+
+    var tsResult = gulp.src(rootDir + "tests/unit/**/*.ts", { base: relativeRootDir })
+        .pipe(tsProject());
+
+    tsResult.once("error", function() {
+        tsResult.once("finish", function() {
+            console.log("Typescript compile failed");
+            process.exit(1);
+        });
+    });
+
+    return tsResult.js.pipe(gulp.dest(relativeRootDir));
+});
+
+/**
+ * Launches the KARMA unit tests in Chrome.
+ */
+gulp.task("tests-unit-debug", gulp.series("tests-unit-transpile", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "tests/unit/karma.conf.js",
+        singleRun: false,
+        browsers: ['Chrome']
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+}));
+
+/**
+ * Launches the KARMA unit tests in phantomJS.
+ */
+gulp.task("tests-babylon-unit", gulp.series("tests-unit-transpile", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "tests/unit/karma.conf.js",
+        singleRun: true
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+}));
+
+/**
+ * Transpiles viewer typescript unit tests. 
+ */
+gulp.task("tests-viewer-validation-transpile", function() {
+
+    let wpBuild = webpackStream(require(relativeRootDir + 'Viewer/webpack.gulp.config.js'), webpack);
+
+    // clean the built directory
+    rmDir("../../Viewer/tests/build/");
+
+    return wpBuild
+        .pipe(rename(function(path) {
+            if (path.extname === '.js') {
+                path.basename = "test";
+            }
+        }))
+        .pipe(gulp.dest("../../Viewer/tests/build/"));
+});
+
+/**
+ * Launches the viewer's KARMA validation tests in chrome in order to debug them.
+ * (Can only be launch locally.)
+ */
+gulp.task("tests-viewer-validation-karma", gulp.series("tests-viewer-validation-transpile", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "Viewer/tests/validation/karma.conf.js",
+        singleRun: false
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+}));
+
+/**
+ * Launches the KARMA validation tests in ff or virtual screen ff on travis for a quick analysis during the build.
+ * (Can only be launch on any branches.)
+ */
+gulp.task("tests-viewer-validation-virtualscreen", gulp.series("tests-viewer-validation-transpile", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "Viewer/tests/validation/karma.conf.js",
+        singleRun: true,
+        browsers: ['Firefox']
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+}));
+
+/**
+ * Launches the KARMA validation tests in browser stack for remote and cross devices validation tests.
+ * (Can only be launch from secure branches.)
+ */
+gulp.task("tests-viewer-validation-browserstack", gulp.series("tests-viewer-validation-transpile", function(done) {
+    if (!process.env.BROWSER_STACK_USERNAME) {
+        done();
+        return;
+    }
+
+    var kamaServerOptions = {
+        configFile: rootDir + "Viewer/tests/validation/karma.conf.browserstack.js",
+        singleRun: true
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+}));
+
+/**
+ * Transpiles viewer typescript unit tests. 
+ */
+gulp.task("tests-viewer-transpile", function() {
+
+    let wpBuild = webpackStream(require(relativeRootDir + 'Viewer/tests/unit/webpack.config.js'), webpack);
+
+    // clean the built directory
+    rmDir("../../Viewer/tests/build/");
+
+    return wpBuild
+        .pipe(rename(function(path) {
+            if (path.extname === '.js') {
+                path.basename = "test";
+            }
+        }))
+        .pipe(gulp.dest("../../Viewer/tests/build/"));
+});
+
+/**
+ * Launches the KARMA unit tests in chrome.
+ * (Can be launch on any branches.)
+ */
+gulp.task("tests-viewer-unit-debug", gulp.series("tests-viewer-transpile", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "Viewer/tests/karma.conf.js",
+        singleRun: false,
+        browsers: ['Chrome']
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+}));
+
+/**
+ * Launches the KARMA unit tests in phantomJS.
+ */
+gulp.task("tests-viewer-unit", gulp.series("tests-viewer-transpile", function(done) {
+    var kamaServerOptions = {
+        configFile: rootDir + "Viewer/tests/karma.conf.js",
+        singleRun: true
+    };
+
+    var server = new karmaServer(kamaServerOptions, done);
+    server.start();
+}));
+
+/**
+ * Launches the KARMA unit tests in phantomJS.
+ */
+gulp.task("tests-unit", gulp.series("tests-babylon-unit", "tests-viewer-unit"));
+
+/**
+ * Launches the KARMA module tests in phantomJS.
+ */
+gulp.task("tests-modules", function() {
+    let testsToRun = require(relativeRootDir + 'tests/modules/tests.json');
+
+    let sequencePromise = Promise.resolve();
+
+    testsToRun.tests.forEach(test => {
+        sequencePromise = sequencePromise.then(() => {
+            console.log("Running " + test.name);
+            let basePath = relativeRootDir + 'tests/modules/' + test.name + '/';
+            
+            rmDir("../../tests/modules/build/");
+            let compilePromise = Promise.resolve();
+
+            if (test.dependencies) {
+                compilePromise = new Promise(function(resolve, reject) {
+                    let counter = 0;
+                    let copyTask = gulp.src(test.dependencies.map(dep => config.build.outputDirectory + '/' + dep)).pipe(rename(function(path) {
+                        path.basename = (counter++) + '';
+                    })).pipe(gulp.dest("../../tests/modules/build/dependencies/"))
+                    copyTask.once("finish", resolve);
+                })
+            }
+            // any compilation needed?
+            if (test.typescript || test.bundler) {
+                //typescript only
+                if (test.typescript && !test.bundler) {
+                    compilePromise = compilePromise.then(() => {
+                        return new Promise(function(resolve, reject) {
+                            var gulpRelativeRootDir = "../../";
+                            var gulpBasePath = gulpRelativeRootDir + 'tests/modules/' + test.name + '/';
+                            var tsProject = typescript.createProject(gulpBasePath + (test.tsconfig || 'tsconfig.json'));
+
+                            var tsResult = gulp.src(gulpBasePath + '/src/**/*.ts', { base: gulpBasePath })
+                                .pipe(tsProject());
+
+                            let error = false;
+                            tsResult.once("error", function() {
+                                error = true;
+                            });
+
+                            let jsPipe = tsResult.js.pipe(gulp.dest(gulpRelativeRootDir + "tests/modules/"));
+
+                            jsPipe.once("finish", function() {
+                                if (error)
+                                    reject('error compiling test');
+                                else
+                                    resolve();
+                            });
+                        });
+                    });
+                } else {
+                    if (test.bundler === 'webpack') {
+                        console.log("webpack");
+                        compilePromise = compilePromise.then(() => {
+                            return new Promise(function(resolve, reject) {
+                                let wpBuild = webpackStream(require(basePath + '/webpack.config.js'), webpack);
+
+                                wpBuild = wpBuild
+                                    .pipe(rename(function(path) {
+                                        if (path.extname === '.js') {
+                                            path.basename = "tests-loader";
+                                        }
+                                    }))
+                                    .pipe(gulp.dest("../../tests/modules/build/"));
+
+                                wpBuild.once("finish", resolve);
+                            })
+                        });
+                    }
+                }
+            }
+
+            return compilePromise.then(() => {
+                return new Promise(function(resolve, reject) {
+                    var kamaServerOptions = {
+                        configFile: rootDir + "tests/modules/karma.conf.js",
+                    };
+
+                    var server = new karmaServer(kamaServerOptions, (err) => {
+                        if (err) {
+                            reject(err);
+                        }
+                        else {
+                            resolve();
+                        }
+                    });
+                    server.start();
+                });
+            })
+        })
+    });
+
+    return sequencePromise;
+});

+ 52 - 0
Tools/Gulp/tasks/gulpTasks-tsLint.js

@@ -0,0 +1,52 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var gulpTslint = require("gulp-tslint");
+var minimist = require("minimist");
+var filter = require('gulp-filter');
+
+// Parse Command Line.
+var commandLineOptions = minimist(process.argv.slice(2), {
+    boolean: ["tsLintFix"]
+});
+
+// Define Constants
+var tsLintConfig = {
+    formatter: "stylish",
+    configuration: "../../tslint.json",
+    fix: commandLineOptions.tsLintFix
+}
+
+// Read the full config.
+var config = require("../../Config/config.js");
+
+/*
+ * TsLint all typescript files from the src directory.
+ */
+var tsLintExternalLibrary = function(settings) {
+    const fxFilter = filter(['**', '!**/*.fragment.ts', '!**/*.vertex.ts', '!**/ShadersInclude/**'], { restore: false });
+    return gulp.src(settings.computed.tsGlob)
+        .pipe(fxFilter)
+        .pipe(gulpTslint(tsLintConfig))
+        .pipe(gulpTslint.report());
+}
+
+/**
+ * Dynamic module linting for external library (mat, post processes, ...).
+ */
+config.lintModules.map(function(module) {
+    // Task will be like moduleName-tsLint
+    gulp.task(module + "-tsLint", function() {
+        var settings = config[module];
+
+        return tsLintExternalLibrary(settings, false);
+    });
+});
+
+/**
+ * Full Librairies tsLint.
+ */
+gulp.task("typescript-libraries-tsLint",
+    gulp.series(config.lintModules.map((module) => {
+        return module + "-tsLint";
+    })
+));

+ 61 - 0
Tools/Gulp/tasks/gulpTasks-typedoc.js

@@ -0,0 +1,61 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var typedoc = require("gulp-typedoc");
+
+// Import Tools.
+var validateTypedoc = require("../helpers/gulp-validateTypedoc");
+
+// Read the full config.
+var config = require("../../Config/config.json");
+
+/**
+ * Generate the TypeDoc JSON output in order to create code metadata.
+ */
+gulp.task("typedoc-generate", function() {
+    return gulp
+        .src(config.build.typedocGenerationFiles)
+        .pipe(typedoc({
+            // TypeScript options (see typescript docs)
+            mode: "modules",
+            module: "commonjs",
+            target: "es5",
+            includeDeclarations: true,
+
+            // Output options (see typedoc docs)
+            json: config.build.typedocJSON,
+
+            // TypeDoc options (see typedoc docs)
+            ignoreCompilerErrors: true,
+
+            readme: "none",
+
+            excludeExternals: true,
+            excludePrivate: true,
+            excludeProtected: true,
+
+            entryPoint: config.build.typedocEntryPoint
+        }));
+});
+
+/**
+ * Validate the TypeDoc JSON output against the current baselin to ensure our code is correctly documented.
+ * (in the newly introduced areas)
+ */
+gulp.task("typedoc-validate", function() {
+    return gulp.src(config.build.typedocJSON)
+        .pipe(validateTypedoc(config.build.typedocValidationBaseline, "BABYLON", true, false));
+});
+
+/**
+ * Generate the validation reference to ensure our code is correctly documented.
+ */
+gulp.task("typedoc-generateValidationBaseline", function() {
+    return gulp.src(config.build.typedocJSON)
+        .pipe(validateTypedoc(config.build.typedocValidationBaseline, "BABYLON", true, true));
+});
+
+/**
+ * Validate the code comments and style case convention through typedoc and
+ * generate the new baseline.
+ */
+gulp.task("typedoc-all", gulp.series("typedoc-generate", "typedoc-validate", "typedoc-generateValidationBaseline"));

+ 118 - 0
Tools/Gulp/tasks/gulpTasks-viewerLibraries.js

@@ -0,0 +1,118 @@
+// Gulp Tools
+var gulp = require("gulp");
+var webpackStream = require("webpack-stream");
+var dtsBundle = require('dts-bundle');
+var merge2 = require("merge2");
+var through = require('through2');
+var path = require("path");
+var rename = require("gulp-rename");
+
+// Gulp Helpers
+var processDeclaration = require('../helpers/gulp-processModuleDeclarationToNamespace');
+var addModuleExports = require("../helpers/gulp-addModuleExports");
+
+// Import Build Config
+var config = require("../../Config/config.json");
+
+/**
+ * Build the viewer
+ */
+var buildViewerLibrary = function(library, settings) {
+    const sequence = [];
+    var outputDirectory = config.build.outputDirectory + settings.build.distOutputDirectory;
+
+    settings.build.outputs.forEach(out => {
+        let wpConfig = require(settings.build.webpack);
+        if (!out.minified) {
+            wpConfig.mode = "development";
+        }
+
+        let wpBuild = webpackStream(wpConfig, require("webpack"));
+
+        //shoud dtsBundle create the declaration?
+        if (settings.build.dtsBundle) {
+            let event = wpBuild
+                .pipe(through.obj(function(file, enc, cb) {
+                    // only declaration files
+                    const isdts = /\.d\.ts$/.test(file.path);
+                    if (isdts) this.push(file);
+                    cb();
+                }))
+                .pipe(gulp.dest(outputDirectory));
+            // dts-bundle does NOT support (gulp) streams, so files have to be saved and reloaded, 
+            // until I fix it
+            event.on("end", function() {
+                // create the file
+                dtsBundle.bundle(settings.build.dtsBundle);
+                // process the declaration
+                let fileLocation = path.join(path.dirname(settings.build.dtsBundle.main), settings.build.dtsBundle.out);
+                processDeclaration(fileLocation, settings.build.umd.packageName, settings.build.umd.processDeclaration);
+            });
+        }
+
+        let build = wpBuild
+            .pipe(through.obj(function(file, enc, cb) {
+                // only pipe js files
+                const isJs = /\.js$/.test(file.path);
+                if (isJs) this.push(file);
+                cb();
+            }))
+            .pipe(addModuleExports(library.moduleDeclaration, { subModule: false, extendsRoot: false, externalUsingBabylon: true, noBabylonInit: true }));
+
+        function processDestination(dest) {
+            var outputDirectory = config.build.outputDirectory + dest.outputDirectory;
+            build = build
+                .pipe(rename(dest.filename))
+                .pipe(gulp.dest(outputDirectory));
+
+            if (dest.addBabylonDeclaration) {
+                // include the babylon declaration
+                if (dest.addBabylonDeclaration === true) {
+                    dest.addBabylonDeclaration = ["babylon.d.ts"];
+                }
+                var decsToAdd = dest.addBabylonDeclaration.map(function(dec) {
+                    return config.build.outputDirectory + '/' + dec;
+                });
+                sequence.unshift(gulp.src(decsToAdd)
+                    .pipe(rename(function(path) {
+                        path.dirname = '';
+                    }))
+                    .pipe(gulp.dest(outputDirectory)))
+            }
+        }
+
+        out.destinations.forEach(dest => {
+            processDestination(dest);
+        });
+
+        sequence.push(build);
+
+    });
+
+    return merge2(sequence);
+}
+
+/**
+ * Dynamic viewer module creation In Serie for WebPack leaks.
+ */
+function buildViewerLibraries(settings) {
+    var tasks = settings.libraries.map(function(library) {
+        var build = function(cb) {
+            return buildViewerLibrary(library, settings);
+        }
+        return build;
+    });
+
+    return gulp.series.apply(this, tasks);
+}
+
+
+/**
+ * Dynamic viewer module creation.
+ */
+config.viewerModules.map(function(module) {
+    var settings = config[module];
+
+    // Build the libraries.
+    gulp.task(module, buildViewerLibraries(settings));
+});

+ 87 - 0
Tools/Gulp/tasks/gulpTasks-watchCore.js

@@ -0,0 +1,87 @@
+// Import Dependencies.
+var gulp = require("gulp");
+let shelljs = require('shelljs');
+var del = require("del");
+
+// Import Helpers.
+var processShaders = require("../helpers/gulp-processShaders");
+var uncommentShaders = require('../helpers/gulp-removeShaderComments');
+var rmDir = require("../../NodeHelpers/rmDir");
+
+// Read the full config.
+var config = require("../../Config/config.js");
+
+// Constants
+var module = "core";
+
+/**
+ * Process shader ts files.
+ */
+gulp.task("watchCore-cleanShaders", function startWatch() {
+    var settings = config[module].computed;
+
+    // Clean shaders.
+    return del(settings.shaderTSGlob, { force: true });
+});
+
+gulp.task("watchCore-buildShaders", gulp.series("watchCore-cleanShaders", function buildShaders() {
+    var settings = config[module].computed;
+    uncommentShaders.displayName = "Uncomment";
+    processShaders.displayName = "Process";
+
+    // Generate shaders.
+    return gulp.src(settings.shaderGlob)
+        .pipe(uncommentShaders())
+        .pipe(processShaders(true));
+}));
+
+/**
+ * Watch ts files and fire repective tasks.
+ */
+gulp.task("watchCore", gulp.series("watchCore-buildShaders", function watch() {
+    var settings = config[module].computed;
+    var library = config[module].libraries[0];
+
+    // Generate output path.
+    var outputDirectory = settings.localDevES6Directory;
+
+    // Clean Folder.
+    rmDir(outputDirectory);
+
+    // Launch TSC.
+    const options = {
+        cwd: settings.srcDirectory,
+        async: true,
+        verbose: true
+    };
+    shelljs.exec(`tsc --importHelpers false --isolatedModules true --declaration false --target es5 --module es2015 --outDir "${outputDirectory}" -w`, options, function(code, stdout, stderr) {
+        if (stderr) {
+            console.log(stderr);
+        }
+        if (stdout) {
+            console.log(stdout);
+        }
+    });
+
+    // Launch shader watch.
+    var watch = gulp.watch(settings.shaderGlob, { interval: 1000 }, function() {
+        console.log(library.output + ": Shaders.");
+    })
+    watch.on("add", (event) => {
+        return gulp.src(event)
+            .pipe(uncommentShaders())
+            .pipe(processShaders(true));
+    });
+    watch.on("change", (event) => {
+        return gulp.src(event)
+            .pipe(uncommentShaders())
+            .pipe(processShaders(true));
+    });
+    watch.on("unlink", (event) => {
+        return gulp.src(event)
+            .pipe(uncommentShaders())
+            .pipe(processShaders(true));
+    });
+
+    return Promise.resolve();
+}));

+ 83 - 0
Tools/Gulp/tasks/gulpTasks-watchLibraries.js

@@ -0,0 +1,83 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var webpack = require('webpack');
+var webpackStream = require("webpack-stream");
+var path = require("path");
+var processShaders = require("../helpers/gulp-processShaders");
+var uncommentShaders = require('../helpers/gulp-removeShaderComments');
+
+// Read the full config.
+var config = require("../../Config/config.js");
+
+/**
+ * Watch ts files and fire repective tasks.
+ */
+gulp.task("watchLibraries", function startWatch() {
+    var tasks = [];
+
+    config.modules.map(function(module) {
+        var settings = config[module].computed;
+        if (!config[module].isCore && settings) {
+            for (var index = 0; index < config[module].libraries.length; index++) {
+                var library = config[module].libraries[index];
+                if (library.preventLoadLibrary) { 
+                    continue;
+                }
+
+                var wpConfig = require(settings.webpackConfigPath);
+
+                // watch on.
+                wpConfig.watch = true;
+                // dev mode and absolute path sourcemaps for debugging
+                wpConfig.mode = "development";
+                wpConfig.devtool = "nosources-source-map";
+
+                // Source Map Remapping for dev tools.
+                wpConfig.output.devtoolModuleFilenameTemplate = (info) => {
+                    info.resourcePath = path.normalize(info.resourcePath);
+
+                    if (!path.isAbsolute(info.resourcePath)) {
+                        info.resourcePath = path.join(settings.srcDirectory, info.resourcePath);
+                    }
+
+                    return `../../../${path.relative(config.computed.rootFolder, info.resourcePath).replace(/\\/g, "/")}`;
+                };
+
+                tasks.push(
+                    gulp.src(settings.shaderGlob)
+                        .pipe(uncommentShaders())
+                        .pipe(processShaders(false))
+                );
+
+                var outputDirectory = settings.localDevUMDDirectory;
+                tasks.push(
+                    webpackStream(wpConfig, webpack)
+                        .pipe(gulp.dest(outputDirectory))
+                );
+
+                var watch = gulp.watch(settings.shaderGlob, { interval: 1000 }, function() {
+                    console.log(library.output + ": Shaders.");
+                })
+                watch.on("add", (event) => {
+                    return gulp.src(event)
+                        .pipe(uncommentShaders())
+                        .pipe(processShaders(false));
+                });
+                watch.on("change", (event) => {
+                    return gulp.src(event)
+                        .pipe(uncommentShaders())
+                        .pipe(processShaders(false));
+                });
+                watch.on("unlink", (event) => {
+                    return gulp.src(event)
+                        .pipe(uncommentShaders())
+                        .pipe(processShaders(false));
+                });
+
+                tasks.push(watch);
+            }
+        }
+    });
+
+    return Promise.resolve();
+});

+ 50 - 0
Tools/Gulp/tasks/gulpTasks-whatsNew.js

@@ -0,0 +1,50 @@
+// Import Dependencies.
+var gulp = require("gulp");
+var fs = require("fs");
+
+/**
+ * Tests the whats new file to ensure changes have been made in the PR.
+ */
+gulp.task("tests-whatsnew", function(done) {
+    // Only checks on Travis
+    if (!process.env.TRAVIS) {
+        done();
+        return;
+    }
+
+    // Only checks on Pull Requests
+    if (process.env.TRAVIS_PULL_REQUEST == "false") {
+        done();
+        return;
+    }
+
+    // Do not check deploy
+    if (process.env.TRAVIS_BRANCH == "preview") {
+        done();
+        return;
+    }
+
+    // Compare what's new with the current one in the preview release folder.
+    const https = require("https");
+    const url = "https://rawgit.com/BabylonJS/Babylon.js/master/dist/preview%20release/what's%20new.md";
+    https.get(url, res => {
+        res.setEncoding("utf8");
+        let oldData = "";
+        res.on("data", data => {
+            oldData += data;
+        });
+        res.on("end", () => {
+            fs.readFile("../../dist/preview release/what's new.md", "utf-8", function(err, newData) {
+                
+            console.log(newData)
+                if (err || oldData != newData) {
+                    done();
+                    return;
+                }
+
+                console.error("What's new file did not change.");
+                process.exit(1);
+            });
+        });
+    });
+});

+ 109 - 0
Tools/NodeHelpers/colorConsole.js

@@ -0,0 +1,109 @@
+var supportsColor = require('color-support');
+
+var hasColors = supportsColor();
+
+var styles = {
+    black: hasColors ? '\x1b[30m' : '',
+    red: hasColors ? '\x1b[31m' : '',
+    green: hasColors ? '\x1b[32m' : '',
+    yellow: hasColors ? '\x1b[33m' : '',
+    blue: hasColors ? '\x1b[34m' : '',
+    magenta: hasColors ? '\x1b[35m' : '',
+    cyan: hasColors ? '\x1b[36m' : '',
+    gray: hasColors ? '\x1b[90m' : '',
+    white: hasColors ? '\x1b[97m' : '',
+
+    bgBlack: hasColors ? '\x1b[40m' : '',
+    bgRed: hasColors ? '\x1b[41m' : '',
+    bgGreen: hasColors ? '\x1b[42m' : '',
+    bgYellow: hasColors ? '\x1b[43m' : '',
+    bgBlue: hasColors ? '\x1b[44m' : '',
+    bgMagenta: hasColors ? '\x1b[45m' : '',
+    bgCyan: hasColors ? '\x1b[46m' : '',
+    bgWhite: hasColors ? '\x1b[47m' : '',
+
+    bold: hasColors ? '\x1b[1m' : '',
+    italic: hasColors ? '\x1b[3m' : '',
+    underline: hasColors ? '\x1b[4m' : '',
+    strikethrough: hasColors ? '\x1b[9m' : '',
+}
+
+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) + ":" +
+        ("0" + time.getSeconds()).slice(-2);
+
+    if (currentColor) {
+        return styles.white + '[' + currentColor + timeInString + clear + styles.white + ']';
+    }
+    else {
+        return styles.white + '[' + styles.gray + timeInString + styles.white + ']';
+    }
+}
+
+function log() {
+    currentColor = styles.gray;
+    var time = getTimestamp();
+    process.stdout.write(time + ' ');
+    currentColor = undefined;
+
+    console.log.apply(console, arguments);
+    return this;
+}
+
+function warn() {
+    currentColor = styles.yellow;
+    var time = getTimestamp();
+    process.stdout.write(time + ' ');
+    currentColor = undefined;
+
+    console.warn.apply(console, arguments);
+    return this;
+}
+
+function err() {
+    currentColor = styles.red;
+    var time = getTimestamp();
+    process.stderr.write(time + ' ');
+    currentColor = undefined;
+
+    console.error.apply(console, arguments);
+    return this;
+}
+
+function success() {
+    currentColor = styles.green;
+    var time = getTimestamp();
+    process.stdout.write(time + ' ');
+    currentColor = undefined;
+
+    console.log.apply(console, arguments);
+    return this;
+}
+
+function emptyLine() {
+    console.log();
+}
+
+for (let style in styles) {
+    Object.defineProperty(String.prototype, style, {
+        get: function() {
+            return styles[style] + this + clear;
+        },
+        enumerable: true,
+        configurable: true
+    });
+}
+
+module.exports = {
+    log,
+    warn,
+    error: err,
+    success,
+    emptyLine
+};

+ 26 - 0
Tools/NodeHelpers/rmDir.js

@@ -0,0 +1,26 @@
+var fs = require("fs-extra");
+
+var rmDir = function(dirPath) {
+    fs.removeSync(dirPath);
+}
+
+module.exports = function(dirPath) {
+    // Retry cause sometimes locked on my mac :-)
+    try {
+        rmDir(dirPath);
+    }
+    catch (e) {
+        try {
+            rmDir(dirPath);
+        }
+        catch (e) {
+            try {
+                rmDir(dirPath);
+            }
+            catch (e) {
+                // Something is definitely wrong here.
+                throw e;
+            }
+        } 
+    }
+};

+ 21 - 0
Tools/Publisher/helpers/getFiles.js

@@ -0,0 +1,21 @@
+// Dependecies.
+const fs = require('fs-extra');
+
+/**
+ * Get Files from folder.
+ */
+const getFiles = function(dir, files_) {
+    files_ = files_ || [];
+    var files = fs.readdirSync(dir);
+    for (var i in files) {
+        var name = dir + '/' + files[i];
+        if (fs.statSync(name).isDirectory()) {
+            getFiles(name, files_);
+        } else {
+            files_.push(name);
+        }
+    }
+    return files_;
+}
+
+module.exports = getFiles;

+ 34 - 0
Tools/Publisher/helpers/publish.js

@@ -0,0 +1,34 @@
+// Dependecies.
+const shelljs = require('shelljs');
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+/**
+ * Publish a package to npm.
+ */
+function publish(version, packageName, publishPath, public) {
+    colorConsole.log('    Publishing ' + packageName.blue.bold + " from " + publishPath.cyan);
+
+    let tag = "";
+    // check for alpha or beta
+    if (version.indexOf('alpha') !== -1 || version.indexOf('beta') !== -1) {
+        tag = ' --tag preview';
+    }
+
+    //publish the respected package
+    var cmd = 'npm publish "' + publishPath + '"' + tag;
+    if (public) {
+       cmd += " --access public";
+    }
+
+    if (process.env.BABYLONJSREALPUBLISH === "true") {
+        colorConsole.log("    Executing: " + cmd.yellow);
+        shelljs.exec(cmd);
+    }
+    else {
+        colorConsole.log("    If publishing enabled: " + cmd.yellow);
+    }
+
+    colorConsole.success('    Publishing ' + "OK".green);
+}
+
+module.exports = publish;

+ 18 - 281
Tools/Publisher/index.js

@@ -1,285 +1,22 @@
-let prompt = require('prompt');
-let shelljs = require('shelljs');
-let fs = require('fs-extra');
-let path = require('path');
-
-let basePath = '../../dist/preview release';
-
-// This can be changed when we have a new major release.
-let minimumDependency = '>=3.3.0-rc.4';
-
-process.env.PATH += (path.delimiter + path.join(__dirname, 'node_modules', '.bin'));
-
-let packages = [
-    {
-        name: 'core',
-        path: '../../'
-    },
-    {
-        name: 'gui',
-        path: basePath + '/gui/'
-    },
-    {
-        name: 'materials',
-        path: basePath + '/materialsLibrary/'
-    },
-    {
-        name: 'postProcess',
-        path: basePath + '/postProcessesLibrary/'
-    },
-    {
-        name: 'gltf2interface',
-        path: basePath + '/gltf2interface/'
-    },
-    {
-        name: 'loaders',
-        path: basePath + '/loaders/'
-    },
-    {
-        name: 'serializers',
-        path: basePath + '/serializers/'
-    },
-    {
-        name: 'proceduralTextures',
-        path: basePath + '/proceduralTexturesLibrary/'
-    },
-    {
-        name: 'inspector',
-        path: basePath + '/inspector/'
-    },
-    {
-        name: 'viewer',
-        path: basePath + '/../../Viewer/',
-        required: [
-            basePath + '/viewer/readme.md',
-            basePath + '/viewer/package.json',
-            basePath + '/viewer/babylon.viewer.js',
-            basePath + '/viewer/babylon.viewer.max.js'
-        ]
-    },
-    {
-        name: 'viewer-assets',
-        path: basePath + '/../../Viewer/build/assets/',
-        required: [
-            basePath + '/../../Viewer/assets/readme.md',
-            basePath + '/../../Viewer/assets/package.json',
-        ]
-    }
-];
-
-function updateEngineVersion(newVersion) {
-    console.log("updating version in babylon.engine.ts");
-    let engineContent = fs.readFileSync("../../src/Engine/babylon.engine.ts").toString();
-    let replaced = engineContent.replace(/(public static get Version\(\): string {\s*return ")(.*)(";\s*})/g, "$1" + newVersion + "$3");
-    fs.writeFileSync("../../src/Engine/babylon.engine.ts", replaced);
-}
-
-function runGulp() {
-    // run gulp typescript-all
-    console.log("Running gulp compilation");
-    let exec = shelljs.exec("gulp typescript-all --gulpfile ../Gulp/gulpfile.js");
-    if (exec.code) {
-        console.log("error during compilation, aborting");
-        process.exit(1);
-    }
-}
-
-function processPackages(version) {
-    packages.forEach((package) => {
-        if (package.name === "core") {
-            processCore(package, version);
-        } else if (package.name === "viewer") {
-            processViewer(package, version);
-        } else {
-
-            if (package.required) {
-                package.required.forEach(file => {
-                    fs.copySync(file, package.path + '/' + path.basename(file));
-                });
-            }
-
-            let packageJson = require(package.path + 'package.json');
-            packageJson.version = version;
-            if (packageJson.dependencies) {
-                Object.keys(packageJson.dependencies).forEach(key => {
-                    if (key.indexOf("babylonjs") !== -1) {
-                        packageJson.dependencies[key] = version;
-                    }
-                });
-            }
-            if (packageJson.peerDependencies) packageJson.peerDependencies.babylonjs = minimumDependency;
-            fs.writeFileSync(package.path + 'package.json', JSON.stringify(packageJson, null, 4));
-
-            publish(version, package.name, package.path);
-        }
-
+// Dependecies.
+const publisher = require('./tasks/main');
+const minimist = require("minimist");
+
+const commandLineOptions = minimist(process.argv.slice(2), {
+    boolean: ["es6"],
+    boolean: ["umd"]
+});
+
+if (commandLineOptions.es6) {
+    publisher(false, {
+        es6: true
     });
 }
-
-//check if logged in
-console.log("Using npm user:");
-let loginCheck = shelljs.exec('npm whoami');
-if (loginCheck.code === 0) {
-    prompt.start();
-
-    prompt.get(['version'], function(err, result) {
-        let version = result.version;
-        updateEngineVersion(version);
-        if (process.argv.indexOf('--no-build') === -1) {
-            runGulp();
-        }
-        processPackages(version);
-
-        console.log("done, please tag git with " + version);
-    });
-} else {
-    console.log('not logged in.');
-}
-
-function processCore(package, version) {
-    let packageJson = require(package.path + 'package.json');
-
-    // make a temporary directory
-    fs.ensureDirSync(basePath + '/package/');
-
-    let files = [
-        {
-            path: basePath + "/babylon.d.ts",
-            objectName: "babylon.d.ts"
-        },
-        {
-            path: basePath + "/es6.js",
-            objectName: "es6.js"
-        },
-        {
-            path: basePath + "/babylon.js",
-            objectName: "babylon.js"
-        },
-        {
-            path: basePath + "/babylon.max.js",
-            objectName: "babylon.max.js"
-        },
-        {
-            path: basePath + "/babylon.worker.js",
-            objectName: "babylon.worker.js"
-        },
-        {
-            path: basePath + "/Oimo.js",
-            objectName: "Oimo.js"
-        },
-        {
-            path: package.path + "readme.md",
-            objectName: "readme.md"
-        }
-    ];
-
-    //copy them to the package path
-    files.forEach(file => {
-        fs.copySync(file.path, basePath + '/package/' + file.objectName);
-    });
-
-    // update package.json
-    packageJson.version = version;
-    console.log("generating file list");
-    let packageFiles = ["package.json"];
-    files.forEach(file => {
-        if (!file.isDir) {
-            packageFiles.push(file.objectName);
-        } else {
-            //todo is it better to read the content and add it? leave it like that ATM
-            packageFiles.push(file.objectName + "/index.js", file.objectName + "/index.d.ts", file.objectName + "/es6.js")
-        }
-    });
-    console.log("updating package.json");
-    packageJson.files = packageFiles;
-    packageJson.main = "babylon.js";
-    packageJson.typings = "babylon.d.ts";
-
-    fs.writeFileSync(basePath + '/package/' + 'package.json', JSON.stringify(packageJson, null, 4));
-
-    publish(version, package.name, basePath + '/package/');
-
-    // remove package directory
-    fs.removeSync(basePath + '/package/');
-
-    // now update the main package.json
-    packageJson.files = packageJson.files.map(file => {
-        if (file !== 'package.json' && file !== 'readme.md') {
-            return 'dist/preview release/' + file;
-        } else {
-            return file;
-        }
+else if (commandLineOptions.umd) {
+    publisher(false, {
+        umd: true
     });
-    packageJson.main = "dist/preview release/babylon.js";
-    packageJson.typings = "dist/preview release/babylon.d.ts";
-
-    fs.writeFileSync(package.path + 'package.json', JSON.stringify(packageJson, null, 4));
-}
-
-function processViewer(package, version) {
-
-    let buildPath = package.path + "build/src/";
-    let projectPath = '../../Viewer';
-
-    if (package.required) {
-        package.required.forEach(file => {
-
-            fs.copySync(file, buildPath + '/' + path.basename(file));
-        });
-    }
-    // the viewer needs to be built using tsc on the viewer's main repository
-
-    // build the viewer
-    console.log("executing " + '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');
-
-    let files = getFiles(buildPath).map(f => f.replace(buildPath + "/", "")).filter(f => f.indexOf("assets/") === -1);
-
-    packageJson.files = files;
-    packageJson.version = version;
-    packageJson.module = "index.js";
-    packageJson.main = "babylon.viewer.js";
-    packageJson.typings = "index.d.ts";
-
-    fs.writeFileSync(buildPath + '/package.json', JSON.stringify(packageJson, null, 4));
-
-    publish(version, package.name, buildPath);
-
-}
-
-function publish(version, packageName, basePath) {
-    console.log('Publishing ' + packageName + " from " + basePath);
-
-    let tagDef = "";
-    // check for alpha or beta
-    if (version.indexOf('alpha') !== -1 || version.indexOf('beta') !== -1 || version.indexOf('-rc.') !== -1) {
-        tagDef = '--tag preview';
-    }
-
-    //publish the respected package
-    console.log("executing " + 'npm publish \"' + basePath + "\"" + ' ' + tagDef);
-    if (process.argv.indexOf('--no-publish') === -1) {
-        shelljs.exec('npm publish \"' + basePath + "\"" + ' ' + tagDef);
-    }
-
-}
-
-function getFiles(dir, files_) {
-    files_ = files_ || [];
-    var files = fs.readdirSync(dir);
-    for (var i in files) {
-        var name = dir + '/' + files[i];
-        if (fs.statSync(name).isDirectory()) {
-            getFiles(name, files_);
-        } else {
-            files_.push(name);
-        }
-    }
-    return files_;
 }
+else {
+    publisher(false);
+}

+ 0 - 20
Tools/Publisher/package.json

@@ -1,20 +0,0 @@
-{
-    "name": "babylonjs-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": "~3.0.1"
-    },
-    "devDependencies": {
-        "gulp": "^4.0.0"
-    }
-}

+ 15 - 0
Tools/Publisher/production.js

@@ -0,0 +1,15 @@
+// Dependecies.
+const shelljs = require('shelljs');
+const publisher = require('./tasks/main');
+
+// Gets the current npm user.
+console.log("Using npm user:");
+let loginCheck = shelljs.exec('npm whoami');
+// If logged in process.
+if (loginCheck.code === 0) {
+    publisher(true);
+}
+// If not logged in error.
+else {
+    console.log('Not logged in, please log in to npm.');
+}

+ 20 - 0
Tools/Publisher/tasks/buildBabylonJSAndDependencies.js

@@ -0,0 +1,20 @@
+// Dependecies.
+const shelljs = require('shelljs');
+const path = require("path");
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+/**
+ * Build the folder with Gulp.
+ */
+function buildBabylonJSAndDependencies() {
+    colorConsole.log("Running gulp compilation");
+    let exec = shelljs.exec("gulp typescript-libraries typescript-es6", {
+        cwd: path.resolve(__dirname, "../../Gulp/")
+    });
+    if (exec.code) {
+        colorConsole.error("Error during compilation, aborting");
+        process.exit(1);
+    }
+}
+
+module.exports = buildBabylonJSAndDependencies;

+ 78 - 0
Tools/Publisher/tasks/main.js

@@ -0,0 +1,78 @@
+// Dependecies.
+const prompt = require('prompt');
+const path = require('path');
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+// Helpers.
+const versionNumberManager = require("./versionNumberManager");
+const buildBabylonJSAndDependencies = require("./buildBabylonJSAndDependencies");
+const processAdditionalPackages = require("./processAdditionalPackages");
+const processUMDPackages = require("./processUMDPackages");
+const processEs6Packages = require("./processEs6Packages");
+const prepareUMDDevPackages = require("./prepareUMDDevPackages");
+const prepareEs6DevPackages = require("./prepareEs6DevPackages");
+const prepareAdditionalDevPackages = require("./prepareAdditionalDevPackages");
+
+// Path management.
+process.env.PATH += (path.delimiter + path.join(__dirname, '../node_modules', '.bin'));
+
+const createVersion = function(version, options) {
+    options = options || {
+        umd: true,
+        es6: true
+    };
+
+    // Publish additional packages from the config.
+    processAdditionalPackages(version);
+    prepareAdditionalDevPackages();
+
+    if (options.umd) {
+        // Create the packages and publish if needed.
+        processUMDPackages(version);
+        // Prepare umd Dev Folder.
+        prepareUMDDevPackages();
+    }
+
+    if (options.es6) {
+        // Do not publish es6 yet.
+        process.env.BABYLONJSREALPUBLISH = false;
+        processEs6Packages(version);
+        // Prepare es6 Dev Folder.
+        prepareEs6DevPackages();
+    }
+}
+
+/**
+ * Main function driving the publication.
+ */
+module.exports = function(production, options) {
+    if (production) {
+        prompt.start();
+
+        prompt.get(['version'], function (err, result) {
+            const version = result.version;
+
+            // Update the engine version if needed.
+            if (!version || !version.length) {
+                colorConsole.error("New version required.");
+                Process.exit(1);
+                return;
+            }
+
+            buildBabylonJSAndDependencies();
+            versionNumberManager.updateEngineVersion(version);
+            versionNumberManager.updateRootPackageVersion(version);
+
+            process.env.BABYLONJSREALPUBLISH = true;
+
+            createVersion(version, options);
+
+            // Invite user to tag with the new version.
+            colorConsole.log("Done, please tag git with " + version);
+        });
+    }
+    else {
+        const version = versionNumberManager.getEngineVersion();
+        createVersion(version, options);
+    }
+};

+ 41 - 0
Tools/Publisher/tasks/prepareAdditionalDevPackages.js

@@ -0,0 +1,41 @@
+// Dependecies.
+const fs = require('fs-extra');
+const rmDir = require("../../NodeHelpers/rmDir");
+const colorConsole = require("../../NodeHelpers/colorConsole");
+var shelljs = require("shelljs");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+
+/**
+ * Prepare a Additional Dev folder npm linked for test purpose.
+ */
+function prepareAdditionalDevPackages() {
+    config.additionalNpmPackages.forEach(package => {
+        colorConsole.log("Prepare " + "AdditionalDev".magenta + " Package: " + package.name.blue.bold);
+
+        let packagePath = package.computed.path;
+        let packageDevPath = package.computed.packageDevDirectory;
+
+        colorConsole.log("    Cleanup " + packageDevPath.cyan);
+        rmDir(packageDevPath);
+
+        colorConsole.log("    Copy Package folder " + packagePath.cyan + " to " + packageDevPath.cyan);
+        fs.copySync(packagePath, packageDevPath);
+
+        colorConsole.log("    Execute Npm Link command");
+        const command = `npm link`;
+        const result = shelljs.exec(command, { 
+            async: false,
+            cwd: packageDevPath
+        });
+
+        if (result.code != 0) {
+            throw "Failed to link the ES6 package."
+        }
+
+        colorConsole.emptyLine();
+    });
+}
+
+module.exports = prepareAdditionalDevPackages;

+ 61 - 0
Tools/Publisher/tasks/prepareEs6DevPackages.js

@@ -0,0 +1,61 @@
+// Dependecies.
+const fs = require('fs-extra');
+const path = require('path');
+const rmDir = require("../../NodeHelpers/rmDir");
+const colorConsole = require("../../NodeHelpers/colorConsole");
+const shelljs = require("shelljs");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+
+/**
+ * Prepare an es6 Dev folder npm linked for test purpose.
+ */
+function prepareEs6DevPackages() {
+    config.modules.forEach(moduleName => {
+        const module = config[moduleName];
+
+        colorConsole.log("Prepare " + "ES6Dev".magenta + " Package: " + moduleName.blue.bold);
+
+        const packagePath = module.computed.packageES6Directory;
+        const packageDevPath = module.computed.packageES6DevDirectory;
+
+        colorConsole.log("    Cleanup " + packageDevPath.cyan);
+        rmDir(packageDevPath);
+
+        colorConsole.log("    Copy Package folder " + packagePath.cyan + " to " + packageDevPath.cyan);
+        fs.copySync(packagePath, packageDevPath);
+
+        const packageES6DevJSONPath = path.join(packageDevPath, "package.json");
+        const packageES6DevJSON = require(packageES6DevJSONPath);
+        for (let dependency in packageES6DevJSON.dependencies) {
+            if (dependency.indexOf("babylon") > -1) {
+                colorConsole.log("    Execute Npm Link " + dependency.yellow);
+                const command = `npm link ${dependency}`;
+                const result = shelljs.exec(command, { 
+                    async: false,
+                    cwd: packageDevPath
+                });
+
+                if (result.code != 0) {
+                    throw "Failed to link the ES6 package."
+                }
+            }
+        }
+
+        colorConsole.log("    Execute Npm Link command");
+        const command = `npm link`;
+        const result = shelljs.exec(command, { 
+            async: false,
+            cwd: packageDevPath
+        });
+
+        if (result.code != 0) {
+            throw "Failed to link the ES6 package."
+        }
+
+        colorConsole.emptyLine();
+    });
+}
+
+module.exports = prepareEs6DevPackages;

+ 61 - 0
Tools/Publisher/tasks/prepareUMDDevPackages.js

@@ -0,0 +1,61 @@
+// Dependecies.
+const fs = require('fs-extra');
+const path = require('path');
+const rmDir = require("../../NodeHelpers/rmDir");
+const colorConsole = require("../../NodeHelpers/colorConsole");
+const shelljs = require("shelljs");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+
+/**
+ * Prepare a UMD Dev folder npm linked for test purpose.
+ */
+function prepareUMDDevPackages() {
+    config.modules.forEach(moduleName => {
+        let module = config[moduleName];
+
+        colorConsole.log("Prepare " + "UMDDev".magenta + " Package: " + moduleName.blue.bold);
+
+        let packagePath = module.computed.packageUMDDirectory;
+        let packageDevPath = module.computed.packageUMDDevDirectory;
+
+        colorConsole.log("    Cleanup " + packageDevPath.cyan);
+        rmDir(packageDevPath);
+
+        colorConsole.log("    Copy Package folder " + packagePath.cyan + " to " + packageDevPath.cyan);
+        fs.copySync(packagePath, packageDevPath);
+
+        const packageUMDDevJSONPath = path.join(packageDevPath, "package.json");
+        const packageUMDDevJSON = require(packageUMDDevJSONPath);
+        for (let dependency in packageUMDDevJSON.dependencies) {
+            if (dependency.indexOf("babylon") > -1) {
+                colorConsole.log("    Execute Npm Link " + dependency.yellow);
+                const command = `npm link ${dependency}`;
+                const result = shelljs.exec(command, { 
+                    async: false,
+                    cwd: packageDevPath
+                });
+
+                if (result.code != 0) {
+                    throw "Failed to link the ES6 package."
+                }
+            }
+        }
+
+        colorConsole.log("    Execute Npm Link command");
+        const command = `npm link`;
+        const result = shelljs.exec(command, { 
+            async: false,
+            cwd: packageDevPath
+        });
+
+        if (result.code != 0) {
+            throw "Failed to link the ES6 package."
+        }
+
+        colorConsole.emptyLine();
+    });
+}
+
+module.exports = prepareUMDDevPackages;

+ 31 - 0
Tools/Publisher/tasks/processAdditionalPackages.js

@@ -0,0 +1,31 @@
+// Dependecies.
+const fs = require('fs-extra');
+const path = require('path');
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+// Helpers.
+const publish = require("../helpers/publish");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+
+/**
+ * Process Additional Packages.
+ */
+function processAdditionalPackages(version) {
+    config.additionalNpmPackages.forEach(package => {
+        colorConsole.log("Process " + "Additional".magenta + " Package: " + package.name.blue.bold);
+
+        let packageJson = require(package.computed.path + '/package.json');
+        packageJson.version = version;
+
+        colorConsole.log("    Update package version to: " + version.green);
+        fs.writeFileSync(path.join(package.computed.path, 'package.json'), JSON.stringify(packageJson, null, 4));
+
+        publish(version, package.name, package.computed.path);
+
+        colorConsole.emptyLine();
+    });
+}
+
+module.exports = processAdditionalPackages;

+ 109 - 0
Tools/Publisher/tasks/processEs6Packages.js

@@ -0,0 +1,109 @@
+// Dependecies.
+const fs = require('fs-extra');
+const path = require('path');
+const rmDir = require("../../NodeHelpers/rmDir");
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+// Helpers.
+const publish = require("../helpers/publish");
+const getFiles = require("../helpers/getFiles");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+const modules = config.modules.concat(config.viewerModules);
+
+/**
+ * Process ES6 Packages.
+ */
+function processEs6Packages(version) {
+    config.modules.forEach(moduleName => {
+        let module = config[moduleName];
+        let es6Config = module.build.es6;
+
+        colorConsole.log("Process " + "ES6".magenta + " Package: " + moduleName.blue.bold);
+
+        let distPath = module.computed.distES6Directory;
+        let packagePath = module.computed.packageES6Directory;
+        let umdPackageJson = require(module.computed.packageJSONPath);
+
+        colorConsole.log("    Cleanup " + packagePath.cyan);
+        rmDir(packagePath);
+
+        colorConsole.log("    Copy Dist folder " + distPath.cyan + " to " + packagePath.cyan);
+        fs.copySync(distPath, packagePath);
+
+        if (module.build.requiredFiles) {
+            module.build.requiredFiles.forEach(file => {
+                let source = path.join(config.computed.rootFolder, file);
+                let destination = path.join(packagePath, path.basename(file));
+                colorConsole.log("    Copy required file: ", source.cyan, destination.cyan);
+                fs.copySync(source, destination);
+            });
+        }
+        if (es6Config.requiredFiles) {
+            es6Config.requiredFiles.forEach(file => {
+                let source = path.join(config.computed.rootFolder, file);
+                let destination = path.join(packagePath, path.basename(file));
+                colorConsole.log("    Copy es6 required file: ", source.cyan, destination.cyan);
+                fs.copySync(source, destination);
+            });
+        }
+
+        umdPackageJson.name = es6Config.packageName;
+        umdPackageJson.version = version;
+        umdPackageJson.main = es6Config.index || "index.js";
+        umdPackageJson.module = es6Config.index || "index.js";
+        umdPackageJson.esnext = es6Config.index || "index.js";
+        umdPackageJson.typings = es6Config.typings || "index.d.ts";
+
+        if (es6Config.packagesFiles) {
+            umdPackageJson.files = es6Config.packagesFiles;
+        }
+        else {
+            let files = getFiles(packagePath)
+                .map(f => f.replace(packagePath + "/", ""))
+                .filter(f => f.indexOf("assets/") === -1);
+            umdPackageJson.files = files;
+        }
+
+        ["dependencies", "peerDependencies", "devDependencies"].forEach(key => {
+            if (umdPackageJson[key]) {
+                let dependencies = umdPackageJson[key];
+                umdPackageJson[key] = {};
+                Object.keys(dependencies).forEach(packageName => {
+                    if (packageName.indexOf("babylonjs") !== -1) {
+                        colorConsole.log("    Checking Internal Dependency: " + packageName.cyan);
+                        let dependencyName = packageName;
+                        for (var moduleName of modules) {
+                            if (config[moduleName] && config[moduleName].build.umd && config[moduleName].build.umd.packageName === packageName) {
+                                if (config[moduleName].build.es6) {
+                                    dependencyName = config[moduleName].build.es6.packageName;
+                                    colorConsole.log("    Replace Dependency: " + packageName.cyan + " by " + dependencyName.cyan);
+                                    break;
+                                }
+                            }
+                        }
+                        umdPackageJson[key][dependencyName] = version;
+                    } else if (!module.isCore) {
+                        umdPackageJson[key][packageName] = dependencies[packageName];
+                    }
+                });
+            }
+        });
+
+        // Inject tslib as a dependency
+        var mainPackageJSONPath = path.join(config.computed.rootFolder, "package.json");
+        var mainPackageJSON = fs.readJSONSync(mainPackageJSONPath);
+        var tslibSemver = mainPackageJSON["devDependencies"]["tslib"];
+        colorConsole.log("    Adding tslib version: ", tslibSemver.yellow);
+        umdPackageJson["dependencies"]["tslib"] = tslibSemver;
+
+        let packageJSONPath = path.join(packagePath, "package.json");
+        fs.writeFileSync(packageJSONPath, JSON.stringify(umdPackageJson, null, 4));
+
+        publish(version, es6Config.packageName, packagePath, true);
+        colorConsole.emptyLine();
+    });
+}
+
+module.exports = processEs6Packages;

+ 120 - 0
Tools/Publisher/tasks/processUMDPackages.js

@@ -0,0 +1,120 @@
+// Dependecies.
+const fs = require('fs-extra');
+const path = require('path');
+const rmDir = require("../../NodeHelpers/rmDir");
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+// Helpers.
+const publish = require("../helpers/publish");
+const processUMDViewer = require("./processUMDViewer");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+const modules = config.modules.concat(config.viewerModules);
+
+/**
+ * Process UMD Packages.
+ */
+function processUMDPackages(version) {
+    modules.forEach(moduleName => {
+        let module = config[moduleName];
+        colorConsole.log("Process " + "UMD".magenta + " Package: " + moduleName.blue.bold);
+
+        if (moduleName === "viewer") {
+            processUMDViewer(module, version);
+        }
+        else {
+            let outputDirectory = module.build.legacyPackageOutputDirectory;
+            if (outputDirectory) {
+                outputDirectory = path.resolve(__dirname, outputDirectory);
+            }
+            else {
+                outputDirectory = module.computed.distDirectory;
+            }
+
+            if (module.build.requiredFiles) {
+                module.build.requiredFiles.forEach(file => {
+                    let source = path.join(config.computed.rootFolder, file);
+                    let destination = path.join(outputDirectory, path.basename(file));
+                    colorConsole.log("    Copy required file: ", source.cyan, destination.cyan);
+                    fs.copySync(source, destination);
+                });
+            }
+
+            // Package version
+            const packageJSONPath = module.computed ?
+                module.computed.packageJSONPath :
+                outputDirectory + '/package.json';
+            let packageJson = require(packageJSONPath);
+            colorConsole.log("    Update package version to: " + version.green);
+            packageJson.version = version;
+
+            // Package dependencies version
+            if (module.build.umd.dependencies) {
+                packageJson.dependencies = module.build.umd.dependencies;
+            }
+
+            // Package dependencies version
+            if (packageJson.dependencies) {
+                Object.keys(packageJson.dependencies).forEach(key => {
+                    if (key.indexOf("babylonjs") !== -1) {
+                        packageJson.dependencies[key] = version;
+                    }
+                });
+            }
+
+            // Package dev dependencies
+            if (module.build.umd.devDependencies) {
+                packageJson.devDependencies = module.build.umd.devDependencies;
+            }
+
+            // Typings
+            if (module.build.umd.typings) {
+                packageJson.typings = module.build.umd.typings;
+            }
+
+            // Main
+            if (module.build.umd.index) {
+                packageJson.main = module.build.umd.index;
+                packageJson.module = module.build.umd.index;
+                packageJson.esnext = module.build.umd.index;
+            }
+
+            // Files
+            if (module.build.umd.packagesFiles) {
+                packageJson.files = module.build.umd.packagesFiles;
+            }
+
+            // Write to disk output directory
+            fs.writeFileSync(path.join(outputDirectory, 'package.json'), JSON.stringify(packageJson, null, 4));
+
+            if (!module.build.legacyPackageOutputDirectory) {
+                let packageUMDPath = module.computed.packageUMDDirectory;
+                colorConsole.log("    Cleanup " + packageUMDPath.cyan);
+                rmDir(packageUMDPath);
+
+                if (module.build.umd.packagesFiles) {
+                    fs.ensureDirSync(packageUMDPath);
+                    for (let file of module.build.umd.packagesFiles.concat(["package.json"])) {
+                        let source = path.join(outputDirectory, file);
+                        let destination = path.join(packageUMDPath, path.basename(file));
+                        colorConsole.log("    Copy Package file: ", source.cyan, destination.cyan);
+                        fs.copyFileSync(source, destination);
+                    }
+                }
+                else {
+                    colorConsole.log("    Copy Package folder " + outputDirectory.cyan + " to " + packageUMDPath.cyan);
+                    fs.copySync(outputDirectory, packageUMDPath);
+                }
+                publish(version, moduleName, packageUMDPath);
+            }
+            else {
+                publish(version, moduleName, outputDirectory);
+            }
+
+            colorConsole.emptyLine();
+        }
+    });
+}
+
+module.exports = processUMDPackages;

+ 58 - 0
Tools/Publisher/tasks/processUMDViewer.js

@@ -0,0 +1,58 @@
+// Dependecies.
+const shelljs = require('shelljs');
+const fs = require('fs-extra');
+const path = require('path');
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+// Helpers.
+const publish = require("../helpers/publish");
+const getFiles = require("../helpers/getFiles");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+
+/**
+ * Special treatment for umd viewer.
+ */
+function processUMDViewer(module, version) {
+
+    let projectPath = '../../../Viewer';
+    let buildPath = path.resolve(__dirname, projectPath + "/build/src/");
+
+    if (module.build.requiredFiles) {
+        module.build.requiredFiles.forEach(file => {
+            let source = path.join(config.computed.rootFolder, file);
+            let destination = path.join(buildPath, path.basename(file));
+            colorConsole.log("    Copy required file: ", source.cyan, destination.cyan);
+            fs.copySync(source, destination);
+        });
+    }
+
+    // The viewer needs to be built using tsc on the viewer's main repository
+    // build the viewer.
+    colorConsole.log("    Executing " + ('tsc -p ' + projectPath).yellow);
+
+    let tscCompile = shelljs.exec('tsc -p ' + projectPath, {
+        cwd: path.resolve(__dirname)
+    });
+    if (tscCompile.code !== 0) {
+        throw new Error("tsc compilation failed");
+    }
+
+    let packageJson = require(path.join(buildPath, 'package.json'));
+
+    let files = getFiles(buildPath).map(f => f.replace(buildPath, "")).filter(f => f.indexOf("assets/") === -1);
+
+    packageJson.files = files;
+    packageJson.version = version;
+    packageJson.module = "index.js";
+    packageJson.main = "babylon.viewer.js";
+    packageJson.typings = "index.d.ts";
+
+    fs.writeFileSync(buildPath + 'package.json', JSON.stringify(packageJson, null, 4));
+
+    publish(version, "viewer", buildPath);
+    colorConsole.emptyLine();
+}
+
+module.exports = processUMDViewer;

+ 57 - 0
Tools/Publisher/tasks/versionNumberManager.js

@@ -0,0 +1,57 @@
+// Dependecies.
+const fs = require('fs-extra');
+const path = require('path');
+const colorConsole = require("../../NodeHelpers/colorConsole");
+
+// Global Variables.
+const config = require("../../Config/config.js");
+const enginePath = path.join(config.core.computed.mainDirectory, "Engines/engine.ts");
+
+/**
+ * Get the version from the engine class for Babylon
+ */
+function getEngineVersion() {
+    colorConsole.log("Get version from engine.ts");
+    const engineContent = fs.readFileSync(enginePath).toString();
+
+    const versionRegex = new RegExp(`public static get Version\\(\\): string {[\\s\\S]*return "([\\s\\S]*?)";[\\s\\S]*}`, "gm");
+    const match = versionRegex.exec(engineContent);
+    if (match && match.length) {
+        const version = match[1];
+        colorConsole.log("Version found: " + version.green);
+        colorConsole.emptyLine();
+        return version;
+    }
+
+    colorConsole.error("Version not found in engine.ts");
+    process.exit(1);
+}
+
+/**
+ * Update the version in the engine class for Babylon
+ */
+function updateEngineVersion(newVersion) {
+    colorConsole.log("Updating version in engine.ts to: " + newVersion.green);
+    let engineContent = fs.readFileSync(enginePath).toString();
+    let replaced = engineContent.replace(/(public static get Version\(\): string {\s*return ")(.*)(";\s*})/g, "$1" + newVersion + "$3");
+    fs.writeFileSync(enginePath, replaced);    
+    colorConsole.emptyLine();
+}
+
+/**
+ * Update the root package.json version
+ */
+function updateRootPackageVersion(newVersion) {
+    colorConsole.log("Updating version in /package.json to: " + newVersion.green);
+    const packageJSONPath = config.core.computed.packageJSONPath;
+    const packageJson = require(packageJSONPath);
+    packageJson.version = newVersion;
+    fs.writeFileSync(packageJSONPath, JSON.stringify(packageJson, null, 4));
+    colorConsole.emptyLine();
+}
+
+module.exports = {
+    getEngineVersion,
+    updateEngineVersion,
+    updateRootPackageVersion
+};

+ 74 - 0
Tools/WebpackPlugins/babylonExternals.js

@@ -0,0 +1,74 @@
+module.exports = function nodeExternals(options) {
+    options = options || {};
+
+    // return an externals function
+    return function(_, request, callback) {
+        if (/^babylonjs-serializers.*$/i.test(request)) {
+            callback(null, {
+                root: "BABYLON",
+                commonjs: "babylonjs-serializers",
+                commonjs2: "babylonjs-serializers",
+                amd: "babylonjs-serializers"
+            });
+        }
+        else if (/^babylonjs-loaders.*$/i.test(request)) {
+            callback(null, {
+                root: "BABYLON",
+                commonjs: "babylonjs-loaders",
+                commonjs2: "babylonjs-loaders",
+                amd: "babylonjs-loaders"
+            });
+        }
+        else if (/^babylonjs-gui.*$/i.test(request)) {
+            callback(null, {
+                root: ["BABYLON", "GUI"],
+                commonjs: "babylonjs-gui",
+                commonjs2: "babylonjs-gui",
+                amd: "babylonjs-gui"
+            });
+        }
+        else if (/^babylonjs.*$/i.test(request)) {
+            callback(null, {
+                root: "BABYLON",
+                commonjs: "babylonjs",
+                commonjs2: "babylonjs",
+                amd: "babylonjs"
+            });
+        }
+        else if (/^@babylonjs\/serializers.*$/i.test(request)) {
+            callback(null, {
+                root: "BABYLON",
+                commonjs: "@babylonjs/serializers",
+                commonjs2: "@babylonjs/serializers",
+                amd: "@babylonjs/serializers"
+            });
+        }
+        else if (/^@babylonjs\/loaders.*$/i.test(request)) {
+            callback(null, {
+                root: "BABYLON",
+                commonjs: "@babylonjs/loaders",
+                commonjs2: "@babylonjs/loaders",
+                amd: "@babylonjs/loaders"
+            });
+        }
+        else if (/^@babylonjs\/gui.*$/i.test(request)) {
+            callback(null, {
+                root: ["BABYLON", "GUI"],
+                commonjs: "@babylonjs/gui",
+                commonjs2: "@babylonjs/gui",
+                amd: "@babylonjs/gui"
+            });
+        }
+        else if (/^@babylonjs\/core.*$/i.test(request)) {
+            callback(null, {
+                root: "BABYLON",
+                commonjs: "@babylonjs/core",
+                commonjs2: "@babylonjs/core",
+                amd: "@babylonjs/core"
+            });
+        }
+        else {
+            callback();
+        }
+    }
+};

+ 66 - 0
Tools/WebpackPlugins/babylonWebpackConfig.js

@@ -0,0 +1,66 @@
+const webpack = require('webpack');
+const babylonExternals = require('./babylonExternals');
+const hardSourceWebpackPlugin = require('hard-source-webpack-plugin');
+
+const config = require("../Config/config.js");
+
+module.exports = function defaultConfig(options) {
+    if (!options) {
+        throw "Options are mandatory to create the config.";
+    }
+
+    const module = options.module;
+    const settings = config[module];
+
+    options.resolveExtensions = options.resolveExtensions || [];
+    options.moduleRules = options.moduleRules || [];
+    options.plugins = options.plugins || [];
+
+    return {
+        context: settings.computed.srcDirectory,
+        entry: {
+            [settings.build.umd.packageName]: settings.libraries[0].computed.entryPath
+        },
+        output: {
+            path: settings.computed.distDirectory,
+            filename: settings.libraries[0].output
+                .replace(".min.", ".")
+                .replace(".max.", "."),
+            libraryTarget: 'umd',
+            library: {
+                root: settings.build.umd.webpackRoot.split("."),
+                amd: settings.build.umd.packageName,
+                commonjs: settings.build.umd.packageName
+            },
+            umdNamedDefine: true
+        },
+        resolve: options.resolve || {
+            extensions: [".ts", ...options.resolveExtensions]
+        },
+        externals: [babylonExternals()],
+        devtool: "none",
+        module: {
+            rules: [{
+                test: /\.tsx?$/,
+                loader: 'awesome-typescript-loader',
+                options: {
+                    configFileName: settings.computed.tsConfigPath,
+                    declaration: false
+                }
+            }, ...options.moduleRules]
+        },
+        mode: "production",
+        performance: {
+            hints: false
+        },
+        plugins: [
+            //new hardSourceWebpackPlugin(),
+            new webpack.WatchIgnorePlugin([
+                /\.js$/,
+                /\.d\.ts$/,
+                /\.fx$/
+            ]),
+            ...options.plugins
+        ]
+    }
+};

+ 0 - 139
Tools/WebpackShaderLoader/index.js

@@ -1,139 +0,0 @@
-//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));
-    });
-};

+ 1 - 1
Viewer/assets/readme.md

@@ -1,6 +1,6 @@
 # Babylon.js Viewer Assets
 
-Babylon's viewer assets package contains all needed binsry assets neeed for the proper operation of the viewer's templating system.
+Babylon's viewer assets package contains all needed binary assets neeed for the proper operation of the viewer's templating system.
 
 This packes is only needed when intalling the viewer's npm package and is installed  and used automatically.
 

+ 0 - 1
Viewer/package.json

@@ -33,7 +33,6 @@
         "html-loader": "^0.5.5",
         "json-loader": "^0.5.7",
         "ts-loader": "^4.4.0",
-        "typescript": "~3.0.1",
         "uglifyjs-webpack-plugin": "^1.2.2",
         "webpack": "^4.16.0",
         "webpack-cli": "^3.0.8",

+ 0 - 6
Viewer/src/externalModules.d.ts

@@ -1,6 +0,0 @@
-/// <reference path="../../dist/babylon.glTF2Interface.d.ts"/>
-/// <reference path="../../dist/preview release/loaders/babylonjs.loaders.d.ts"/>
-
-declare module "babylonjs-loaders" {
-    export = BABYLON;
-}

+ 2 - 2
Viewer/src/loader/plugins/msftLodLoaderPlugin.ts

@@ -1,5 +1,5 @@
 import { ISceneLoaderPlugin, ISceneLoaderPluginAsync } from 'babylonjs';
-import { GLTF2, IGLTFLoaderExtension } from 'babylonjs-loaders';
+import { IGLTFLoaderExtension, GLTF2 } from 'babylonjs-loaders';
 
 import { ViewerModel } from '../../model/viewerModel';
 import { ILoaderPlugin } from './loaderPlugin';
@@ -17,7 +17,7 @@ export class MSFTLodLoaderPlugin implements ILoaderPlugin {
 
     public onExtensionLoaded(extension: IGLTFLoaderExtension) {
         if (extension.name === "MSFT_lod" && this._model.configuration.loaderConfiguration) {
-            const MSFT_lod = extension as GLTF2.Loader.Extensions.MSFT_lod;
+            const MSFT_lod = extension as GLTF2.MSFT_lod;
             MSFT_lod.enabled = !!this._model.configuration.loaderConfiguration.progressiveLoading;
             MSFT_lod.maxLODsToLoad = this._model.configuration.loaderConfiguration.maxLODsToLoad || Number.MAX_VALUE;
         }

+ 5 - 5
Viewer/src/loader/plugins/telemetryLoaderPlugin.ts

@@ -1,7 +1,7 @@
 import { ILoaderPlugin } from "./loaderPlugin";
 import { telemetryManager } from "../../managers/telemetryManager";
 import { ViewerModel } from "../../model/viewerModel";
-import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
+import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, PrecisionDate } from "babylonjs";
 
 export class TelemetryLoaderPlugin implements ILoaderPlugin {
 
@@ -12,19 +12,19 @@ export class TelemetryLoaderPlugin implements ILoaderPlugin {
 
     public onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel) {
         this._model = model;
-        this._loadStart = Tools.Now;
+        this._loadStart = PrecisionDate.Now;
     }
 
     public onLoaded(model: ViewerModel) {
         telemetryManager.broadcast("Model Loaded", model.getViewerId(), {
             model: model,
-            loadTime: Tools.Now - this._loadStart
+            loadTime: PrecisionDate.Now - this._loadStart
         });
         telemetryManager.flushWebGLErrors(model.rootMesh.getEngine(), model.getViewerId());
     }
 
     public onError(message: string, exception: any) {
-        this._loadEnd = Tools.Now;
+        this._loadEnd = PrecisionDate.Now;
         telemetryManager.broadcast("Load Error", this._model.getViewerId(), {
             model: this._model,
             loadTime: this._loadEnd - this._loadStart
@@ -34,7 +34,7 @@ export class TelemetryLoaderPlugin implements ILoaderPlugin {
     }
 
     public onComplete() {
-        this._loadEnd = Tools.Now;
+        this._loadEnd = PrecisionDate.Now;
         telemetryManager.broadcast("Load Complete", this._model.getViewerId(), {
             model: this._model,
             loadTime: this._loadEnd - this._loadStart

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 28 - 28
Viewer/src/managers/sceneManager.ts


+ 4 - 3
Viewer/src/model/viewerModel.ts

@@ -1,5 +1,6 @@
 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 { GLTFFileLoader } from "babylonjs-loaders";
+import { IAsset } from "babylonjs-gltf2interface";
 import { IModelConfiguration } from "../configuration/interfaces/modelConfiguration";
 import { IModelAnimationConfiguration } from "../configuration/interfaces/modelAnimationConfiguration";
 import { IModelAnimation, GroupModelAnimation, AnimationPlayMode, ModelAnimationConfiguration, EasingFunction, AnimationState } from "./modelAnimation";
@@ -90,7 +91,7 @@ export class ViewerModel implements IDisposable {
      */
     public loadId: number;
 
-    public loadInfo: GLTF2.IAsset;
+    public loadInfo: IAsset;
     private _loadedUrl: string;
     private _modelConfiguration: IModelConfiguration;
 
@@ -623,7 +624,7 @@ export class ViewerModel implements IDisposable {
         animations: Animation[],
         duration: number,
         easingFunction: any,
-        easingMode: number = BABYLON.EasingFunction.EASINGMODE_EASEINOUT,
+        easingMode: number = 2, // BABYLON.EasingFunction.EASINGMODE_EASEINOUT,
         onAnimationEnd: () => void): void {
 
         if (easingFunction) {

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

@@ -461,7 +461,7 @@ export abstract class AbstractViewer {
         // Create the screenshot
         return new Promise<string>((resolve, reject) => {
             try {
-                BABYLON.Tools.CreateScreenshot(this.engine, this.sceneManager.camera, { width, height }, (data) => {
+                Tools.CreateScreenshot(this.engine, this.sceneManager.camera, { width, height }, (data) => {
                     if (callback) {
                         callback(data);
                     }

+ 0 - 17
Viewer/tests/package.json

@@ -1,17 +0,0 @@
-{
-    "name": "babylonjsviewerunittest",
-    "version": "7.7.7",
-    "description": "Unit Tests Suite For Babylon.js' viewer",
-    "main": "",
-    "repository": {
-        "url": "https://github.com/BabylonJS/Babylon.js/"
-    },
-    "readme": "https://github.com/BabylonJS/Babylon.js/edit/master/readme.md",
-    "license": "(Apache-2.0)",
-    "devDependencies": {
-        "@types/mocha": "2.2.46",
-        "@types/chai": "^4.1.0",
-        "@types/sinon": "^4.1.3",
-        "typescript": "~3.0.1"
-    }
-}

+ 6 - 11
Viewer/tests/unit/src/configuration/updateConfiguration.ts

@@ -1,5 +1,6 @@
 import { Helper } from "../../../commons/helper";
 import { assert, expect, should } from "../viewerReference";
+import { SceneOptimizer, SceneOptimizerOptions } from "babylonjs";
 
 export let name = "configuration update";
 
@@ -262,24 +263,19 @@ describe(name + " scene optimizer", () => {
         let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
 
         let started = false;
-        let constructed = false;
 
-        let optimizerFunction = BABYLON.SceneOptimizer;
+        let optimizerFunction = SceneOptimizer;
 
         //mock!
-        (<any>BABYLON.SceneOptimizer) = function() {
-            constructed = true;
-        };
-
-        BABYLON.SceneOptimizer.prototype.start = function() {
+        SceneOptimizer.prototype.start = function() {
             started = true;
         };
 
-        BABYLON.SceneOptimizer.prototype.stop = function() {
+        SceneOptimizer.prototype.stop = function() {
             started = false;
         };
 
-        BABYLON.SceneOptimizer.prototype.dispose = function() {
+        SceneOptimizer.prototype.dispose = function() {
         };
 
         viewer.onInitDoneObservable.add(() => {
@@ -292,7 +288,6 @@ describe(name + " scene optimizer", () => {
 
             assert.isDefined(viewer.sceneManager.sceneOptimizer);
             assert.isTrue(started);
-            assert.isTrue(constructed);
 
             viewer.updateConfiguration({
                 optimizer: false
@@ -301,7 +296,7 @@ describe(name + " scene optimizer", () => {
             assert.isUndefined(viewer.sceneManager.sceneOptimizer);
             assert.isFalse(started);
 
-            BABYLON.SceneOptimizer = optimizerFunction;
+            //SceneOptimizer = optimizerFunction;
 
             viewer.dispose();
             done();

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

@@ -1,6 +1,7 @@
 import { Helper } from "../../../commons/helper";
 import { assert, expect, should } from "../viewerReference";
 import { DefaultViewer, AbstractViewer, Version, viewerManager } from "../../../../src";
+import { PBRMaterial } from "babylonjs";
 
 export let name = "scene manager";
 
@@ -43,7 +44,7 @@ describe(name, function() {
     it("should set the default material to be PBR-Enabled per default", (done) => {
         let viewer = Helper.getNewViewerInstance();
         viewer.onInitDoneObservable.add(() => {
-            assert.isTrue(viewer.sceneManager.scene.defaultMaterial instanceof BABYLON.PBRMaterial);
+            assert.isTrue(viewer.sceneManager.scene.defaultMaterial instanceof PBRMaterial);
 
             viewer.dispose();
             done();

+ 2 - 1
Viewer/tests/unit/src/viewer/viewer.ts

@@ -1,6 +1,7 @@
 import { Helper } from "../../../commons/helper";
 import { assert, expect, should } from "../viewerReference";
 import { DefaultViewer, AbstractViewer, Version, viewerManager } from "../../../../src";
+import { Engine } from "babylonjs";
 
 export let name = "viewer Tests";
 
@@ -119,7 +120,7 @@ describe('Viewer', function() {
 
     it('should have a version', (done) => {
         assert.exists(Version, "Viewer should have a version");
-        assert.equal(Version, BABYLON.Engine.Version, "Viewer version should equal to Babylon's engine version");
+        assert.equal(Version, Engine.Version, "Viewer version should equal to Babylon's engine version");
         done();
     });
 

+ 3 - 3
Viewer/tests/unit/src/viewerReference.ts

@@ -1,6 +1,6 @@
-/// <reference path="../../node_modules/@types/chai/index.d.ts" />
-/// <reference path="../../node_modules/@types/mocha/index.d.ts" />
-/// <reference path="../../node_modules/@types/sinon/index.d.ts" />
+/// <reference path="../../../../node_modules/@types/chai/index.d.ts" />
+/// <reference path="../../../../node_modules/@types/mocha/index.d.ts" />
+/// <reference path="../../../../node_modules/@types/sinon/index.d.ts" />
 /*
  * Create a constant with the ChaiJS' expect module just to make the code more readable.
  */

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

@@ -26,10 +26,10 @@
                 "../../../../dist/preview release/babylon.d.ts"
             ],
             "babylonjs-loaders": [
-                "../../../src/externalModules.d.ts"
+                "../../../../dist/preview release/loaders/babylonjs.loaders.module.d.ts"
             ],
             "babylonjs-gltf2interface": [
-                "../../../../dist/babylon.glTF2Interface.d.ts"
+                "../../../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
             ],
             "babylonjs-viewer-assets": [
                 "../../src/assets/"

+ 0 - 6
Viewer/tests/unit/webpack.config.js

@@ -19,12 +19,6 @@ module.exports = {
             "babylonjs-viewer-assets": __dirname + '/../../src/assets/index.ts'
         }
     },
-    externals: {
-        // until physics will be integrated in the viewer, ignore cannon
-        cannon: 'CANNON',
-        oimo: 'OIMO',
-        "earcut": true
-    },
     mode: "development",
     devtool: 'source-map',
     module: {

+ 4 - 2
Viewer/tests/validation/validation.js

@@ -113,11 +113,12 @@ function evaluate(test, resultCanvas, result, renderImage, index, waitRing, done
 
     // gl check
     var gl = currentViewer.engine._gl;
-    if (gl.getError() !== 0) {
+    var err = gl.getError();
+    if (err !== 0) {
         result.classList.add("failed");
         result.innerHTML = "×";
         testRes = false;
-        console.log('%c failed (gl error)', 'color: red');
+        console.log('%c failed (gl error: ' + err + ')', 'color: red');
     } else {
 
         // Visual check
@@ -205,6 +206,7 @@ function runTest(index, done) {
     configuration.engine = configuration.engine || {};
     configuration.engine.engineOptions = configuration.engine.engineOptions || {};
     configuration.engine.engineOptions.preserveDrawingBuffer = true;
+    // configuration.engine.engineOptions.disableWebGL2Support = true;
 
     //cancel camera behvaviors for the tests
     configuration.camera = configuration.camera || {};

+ 3 - 8
Viewer/tsconfig-gulp.json

@@ -23,13 +23,13 @@
         "rootDir": "./",
         "paths": {
             "babylonjs": [
-                "../../dist/preview release/babylon.d.ts"
+                "../../dist/preview release/babylon.module.d.ts"
             ],
             "babylonjs-loaders": [
-                "externalModules.d.ts"
+                "../../dist/preview release/loaders/babylonjs.loaders.module.d.ts"
             ],
             "babylonjs-gltf2interface": [
-                "../../dist/babylon.glTF2Interface.d.ts"
+                "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
             ],
             "deepmerge": [
                 "./helper/deepmerge.d.ts"
@@ -43,11 +43,6 @@
         },
         "outDir": "./build"
     },
-    "exclude": [
-        "node_modules",
-        "dist",
-        "tests"
-    ],
     "include": [
         "./src/**/*.ts"
     ]

+ 3 - 3
Viewer/tsconfig.json

@@ -23,13 +23,13 @@
         "rootDir": "./",
         "paths": {
             "babylonjs": [
-                "../../dist/preview release/babylon.d.ts"
+                "../../dist/preview release/babylon.module.d.ts"
             ],
             "babylonjs-loaders": [
-                "externalModules.d.ts"
+                "../../dist/preview release/loaders/babylonjs.loaders.module.d.ts"
             ],
             "babylonjs-gltf2interface": [
-                "../../dist/babylon.glTF2Interface.d.ts"
+                "../../dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts"
             ],
             "deepmerge": [
                 "./helper/deepmerge.d.ts"

+ 0 - 6
Viewer/webpack.config.js

@@ -65,12 +65,6 @@ module.exports = /*[
                 "babylonjs-viewer-assets": __dirname + '/src/assets/index.ts'
             }
         },
-        externals: {
-            // until physics will be integrated in the viewer, ignore cannon
-            cannon: 'CANNON',
-            oimo: 'OIMO',
-            earcut: true
-        },
         mode: "development",
         devtool: 'source-map',
         plugins: [

+ 0 - 5
Viewer/webpack.gulp.config.js

@@ -11,11 +11,6 @@ module.exports = {
         library: 'BabylonViewer',
         umdNamedDefine: true
     },
-    externals: {
-        cannon: 'CANNON',
-        oimo: 'OIMO',
-        "earcut": true
-    },
     resolve: {
         extensions: ['.ts', '.js'],
         alias: {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 53120 - 51510
dist/preview release/babylon.d.ts


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 16 - 1
dist/preview release/babylon.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 137943 - 122318
dist/preview release/babylon.max.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
dist/preview release/babylon.max.js.map


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 55834 - 0
dist/preview release/babylon.module.d.ts


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


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác