Selaa lähdekoodia

Merge branch 'master' into master

Denis Radin 7 vuotta sitten
vanhempi
commit
77ab683e6c
100 muutettua tiedostoa jossa 79445 lisäystä ja 50558 poistoa
  1. 15 1
      .travis.yml
  2. 9 1
      .vscode/settings.json
  3. 7340 4951
      Playground/babylon.d.txt
  4. 5 2
      Tools/Gulp/config.json
  5. 15 1
      Tools/Gulp/gulp-validateTypedoc.js
  6. 58 14
      Tools/Gulp/gulpfile.js
  7. 40 17
      Tools/Publisher/index.js
  8. 3 0
      Tools/Publisher/package.json
  9. 4 3
      Viewer/dist/basicExample.html
  10. 5 0
      Viewer/dist/config.json
  11. 18444 15388
      Viewer/dist/viewer.js
  12. 1 1
      Viewer/dist/viewer.min.js
  13. 10 10
      Viewer/package.json
  14. 5 15
      Viewer/src/configuration/configuration.ts
  15. 28 17
      Viewer/src/configuration/loader.ts
  16. 1 2
      Viewer/src/configuration/mappers.ts
  17. 7 1
      Viewer/src/configuration/types/default.ts
  18. 2 1
      Viewer/src/configuration/types/index.ts
  19. 40 0
      Viewer/src/eventManager.ts
  20. 60 23
      Viewer/src/templateManager.ts
  21. 42 59
      Viewer/src/viewer/defaultViewer.ts
  22. 47 10
      Viewer/src/viewer/viewer.ts
  23. 1 1
      Viewer/src/viewer/viewerManager.ts
  24. 251 0
      dist/babylon.glTFInterface.d.ts
  25. 11135 8840
      dist/preview release/babylon.d.ts
  26. 51 51
      dist/preview release/babylon.js
  27. 2553 467
      dist/preview release/babylon.max.js
  28. 19088 0
      dist/preview release/babylon.module.d.ts
  29. 52 52
      dist/preview release/babylon.worker.js
  30. 3459 1169
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  31. 55 55
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  32. 2499 468
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  33. 2501 470
      dist/preview release/customConfigurations/minimalGLTFViewer/es6.js
  34. 2555 469
      dist/preview release/es6.js
  35. 70 1
      dist/preview release/gui/babylon.gui.d.ts
  36. 74 1
      dist/preview release/gui/babylon.gui.js
  37. 3 3
      dist/preview release/gui/babylon.gui.min.js
  38. 70 1
      dist/preview release/gui/babylon.gui.module.d.ts
  39. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  40. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  41. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  42. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  43. 0 3
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  44. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  45. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  46. 0 3
      dist/preview release/loaders/babylon.glTFFileLoader.js
  47. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  48. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  49. 0 3
      dist/preview release/loaders/babylonjs.loaders.js
  50. 3 3
      dist/preview release/loaders/babylonjs.loaders.min.js
  51. 2 2
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  52. 1 3
      dist/preview release/loaders/package.json
  53. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  54. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  55. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  56. 3 3
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  57. 1 3
      dist/preview release/materialsLibrary/package.json
  58. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  59. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  60. 1 1
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  61. 1 3
      dist/preview release/postProcessesLibrary/package.json
  62. 1 3
      dist/preview release/proceduralTexturesLibrary/package.json
  63. 173 42
      dist/preview release/serializers/babylon.glTF2Serializer.d.ts
  64. 997 559
      dist/preview release/serializers/babylon.glTF2Serializer.js
  65. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  66. 997 559
      dist/preview release/serializers/babylonjs.serializers.js
  67. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  68. 173 42
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  69. 1 3
      dist/preview release/serializers/package.json
  70. 4033 16203
      dist/preview release/typedocValidationBaseline.json
  71. 65 65
      dist/preview release/viewer/babylon.viewer.js
  72. 7 2
      dist/preview release/what's new.md
  73. 11 0
      gui/src/advancedDynamicTexture.ts
  74. 65 3
      gui/src/controls/textBlock.ts
  75. 2 5
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  76. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  77. 1 1
      package.json
  78. 25 10
      serializers/src/glTF/2.0/babylon.glTFData.ts
  79. 516 224
      serializers/src/glTF/2.0/babylon.glTFExporter.ts
  80. 198 0
      serializers/src/glTF/2.0/babylon.glTFMaterial.ts
  81. 45 21
      serializers/src/glTF/2.0/babylon.glTFSerializer.ts
  82. 19 0
      src/Actions/babylon.actionManager.ts
  83. 5 1
      src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.ts
  84. 98 5
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  85. 204 26
      src/Cameras/VR/babylon.webVRCamera.ts
  86. 11 9
      src/Cameras/babylon.camera.ts
  87. 14 1
      src/Cameras/babylon.cameraInputsManager.ts
  88. 25 2
      src/Cameras/babylon.deviceOrientationCamera.ts
  89. 9 1
      src/Cameras/babylon.freeCamera.ts
  90. 15 1
      src/Collisions/babylon.collisionCoordinator.ts
  91. 37 18
      src/Engine/babylon.engine.ts
  92. 156 2
      src/Materials/Textures/babylon.internalTexture.ts
  93. 29 0
      src/Materials/Textures/babylon.internalTextureTracker.ts
  94. 212 93
      src/Materials/Textures/babylon.videoTexture.ts
  95. 49 0
      src/Math/babylon.math.ts
  96. 2 0
      src/Mesh/babylon.abstractMesh.ts
  97. 601 35
      src/Mesh/babylon.geometry.ts
  98. 11 3
      src/Mesh/babylon.mesh.ts
  99. 1 0
      src/Mesh/babylon.vertexBuffer.ts
  100. 0 0
      src/Particles/babylon.boxParticleEmitter.ts

+ 15 - 1
.travis.yml

@@ -3,6 +3,13 @@ dist: trusty
 language: node_js
 node_js:
 - '6'
+cache:
+  directories:
+    - Tools/Gulp/node_modules
+    - Playground/node_modules
+    - tests/unit/node_modules
+git:
+  depth: 3
 before_script:
 - travis_retry npm install -g gulp
 - cd ./Tools/Gulp
@@ -10,7 +17,14 @@ before_script:
 - "export DISPLAY=:99.0"
 - "sh -e /etc/init.d/xvfb start"
 - sleep 3 # give xvfb some time to start
-script: gulp
+script: 
+- gulp tests-whatsnew
+- set -e
+- gulp typescript-all
+- gulp typedoc-all
+- gulp tests-unit
+- travis_retry gulp tests-validation-virtualscreen
+- travis_retry gulp tests-validation-browserstack
 notifications:
   slack:
     secure: TBYDAN8Dlkx3dM+Q5ClAZem7agAhQ1oB/fGT665qn7D+j2YfWChvlfXegvXL4LPDmQgbI0UfazcjWId5a0EwmmPkRb+kMJItPiMt5jiIp2WKoZQ+qob6H9tBCRJbbpWM430wiPeKfBfbcZP/XSlpVMWhgU5ogAFDSUKjvHT7IuE=

+ 9 - 1
.vscode/settings.json

@@ -11,7 +11,15 @@
         "**/node_modules": true,
         "**/temp": true,
         "**/.temp": true,
-        "**/*.d.ts": true,
+        "src/**/*.d.ts": true,
+        "gui/**/*.d.ts": true,
+        "inspector/**/*.d.ts": true,
+        "loaders/**/*.d.ts": true,
+        "materialsLibrary/**/*.d.ts": true,
+        "postProcessesLibrary/**/*.d.ts": true,
+        "proceduralTexturesLibrary/**/*.d.ts": true,
+        "serielazers/**/*.d.ts": true,
+        "viewer/**/*.d.ts": true,
         "**/*.js.map": true,
         "**/*.js.fx": true,
         "**/*.js": { 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7340 - 4951
Playground/babylon.d.txt


+ 5 - 2
Tools/Gulp/config.json

@@ -16,7 +16,7 @@
         "srcOutputDirectory": "../../src/",
         "currentConfig": "all",
         "typedocJSON": "../../.temp/babylon.typedoc.json",
-        "typedocValidationBaseline": "../../dist/preview release/typedocValidationBaseline.json" 
+        "typedocValidationBaseline": "../../dist/preview release/typedocValidationBaseline.json"
     },
     "buildConfigurations": {
         "all": [
@@ -177,6 +177,7 @@
                 "../../src/Tools/babylon.observable.js",
                 "../../src/Tools/babylon.smartArray.js",
                 "../../src/Tools/babylon.tools.js",
+                "../../src/Tools/babylon.promise.js",
                 "../../src/States/babylon.alphaCullingState.js",
                 "../../src/States/babylon.depthCullingState.js",
                 "../../src/States/babylon.stencilState.js",
@@ -195,6 +196,7 @@
                 "../../src/babylon.assetContainer.js",
                 "../../src/Mesh/babylon.buffer.js",
                 "../../src/Mesh/babylon.vertexBuffer.js",
+                "../../src/Materials/Textures/babylon.internalTextureTracker.js",
                 "../../src/Materials/Textures/babylon.internalTexture.js",
                 "../../src/Materials/Textures/babylon.baseTexture.js",
                 "../../src/Materials/Textures/babylon.texture.js",
@@ -1458,7 +1460,8 @@
                 "files": [
                     "../../serializers/src/glTF/2.0/babylon.glTFSerializer.ts",
                     "../../serializers/src/glTF/2.0/babylon.glTFExporter.ts",
-                    "../../serializers/src/glTF/2.0/babylon.glTFData.ts"
+                    "../../serializers/src/glTF/2.0/babylon.glTFData.ts",
+                    "../../serializers/src/glTF/2.0/babylon.glTFMaterial.ts"
                 ],
                 "output": "babylon.glTF2Serializer.js"
             }

+ 15 - 1
Tools/Gulp/gulp-validateTypedoc.js

@@ -238,7 +238,15 @@ Validate.prototype.getContents = function () {
  * Validate a TypeDoc JSON file
  */
 Validate.prototype.validateTypedoc = function (json) {
-    var namespaces = json.children[0].children;
+    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;
 
     var containerNode;
@@ -437,6 +445,12 @@ Validate.prototype.validateComment = function(node) {
         return true;
     }
 
+    // Return true for overwrited properties
+    if (node.overwrites) {
+        return true;
+    }
+    
+
     if (node.comment) {
 
         if (node.comment.text || node.comment.shortText) {

+ 58 - 14
Tools/Gulp/gulpfile.js

@@ -27,13 +27,14 @@ var sass = require("gulp-sass");
 var webpack = require("webpack-stream");
 var typedoc = require("gulp-typedoc");
 var validateTypedoc = require("./gulp-validateTypedoc");
+var request = require('request');
+var fs = require("fs");
+var karmaServer = require('karma').Server;
 
 var config = require("./config.json");
 
 var del = require("del");
 
-var karmaServer = require('karma').Server;
-
 var debug = require("gulp-debug");
 var includeShadersStream;
 var shadersStream;
@@ -252,14 +253,11 @@ gulp.task("typescript-compile", function () {
 
     //If this gulp task is running on travis, file the build!
     if (process.env.TRAVIS) {
-        var error = false;
-        tsResult.on("error", function () {
-            error = true;
-        }).on("end", function () {
-            if (error) {
+        tsResult.once("error", function () {
+            tsResult.once("finish", function () {
                 console.log("Typescript compile failed");
                 process.exit(1);
-            }
+            });
         });
     }
 
@@ -593,14 +591,11 @@ gulp.task("modules-compile", function () {
 
     // If this gulp task is running on travis
     if (process.env.TRAVIS) {
-        var error = false;
-        tsResult.on("error", function () {
-            error = true;
-        }).on("end", function () {
-            if (error) {
+        tsResult.once("error", function () {
+            tsResult.once("finish", function () {
                 console.log("Typescript compile failed");
                 process.exit(1);
-            }
+            });
         });
     }
 
@@ -906,6 +901,13 @@ gulp.task("tests-unit-transpile", function (done) {
 
     var tsResult = gulp.src("../../tests/unit/**/*.ts", { base: "../../" })
         .pipe(tsProject());
+    
+    tsResult.once("error", function () {
+        tsResult.once("finish", function () {
+            console.log("Typescript compile failed");
+            process.exit(1);
+        });
+    });
  
     return tsResult.js.pipe(gulp.dest("../../"));
 });
@@ -938,3 +940,45 @@ gulp.task("tests-unit", ["tests-unit-transpile"], function (done) {
     var server = new karmaServer(kamaServerOptions, done);
     server.start();
 });
+
+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) {
+                if (err || oldData != newData) {
+                    done();
+                    return;
+                }
+                
+                console.error("What's new file did not change.");
+                process.exit(1);
+            });
+        });
+    });
+});

+ 40 - 17
Tools/Publisher/index.js

@@ -46,6 +46,39 @@ let packages = [
     }
 ];
 
+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
+    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() {
+    packages.forEach((package) => {
+        if (package.name === "core") {
+            processCore(package, version);
+        } else {
+            let packageJson = require(package.path + 'package.json');
+            packageJson.version = version;
+            if (packageJson.peerDependencies) packageJson.peerDependencies.babylonjs = minimumDependency;
+            fs.writeFileSync(package.path + 'package.json', JSON.stringify(packageJson, null, 4));
+            console.log('Publishing ' + package.name + " from " + package.path);
+            //publish the respected package
+            shelljs.exec('npm publish \"' + package.path + "\"");
+        }
+
+    });
+}
+
 //check if logged in
 console.log("Using npm user:");
 let loginCheck = shelljs.exec('npm whoami');
@@ -55,21 +88,11 @@ if (loginCheck.code === 0) {
 
     prompt.get(['version'], function (err, result) {
         let version = result.version;
-        packages.forEach((package) => {
-            if (package.name === "core") {
-                processCore(package, version);
-            } else {
-                let packageJson = require(package.path + 'package.json');
-                packageJson.version = version;
-                if (packageJson.peerDependencies) packageJson.peerDependencies.babylonjs = minimumDependency;
-                fs.writeFileSync(package.path + 'package.json', JSON.stringify(packageJson, null, 4));
-                console.log('Publishing ' + package.name + " from " + package.path);
-                //publish the respected package
-                shelljs.exec('npm publish \"' + package.path + "\"");
-            }
-
-        });
-        console.log("done, please don't forget to commit the changes")
+        updateEngineVersion(version);
+        runGulp();
+        processPackages();
+
+        console.log("done, please tag git with " + version);
     });
 } else {
     console.log('not logged in.');
@@ -143,7 +166,7 @@ function processCore(package, version) {
     });
     console.log("updating package.json");
     packageJson.files = packageFiles;
-    packageJson.main = "babylon.max.js";
+    packageJson.main = "babylon.js";
     packageJson.typings = "babylon.d.ts";
 
     fs.writeFileSync(basePath + '/package/' + 'package.json', JSON.stringify(packageJson, null, 4));
@@ -163,7 +186,7 @@ function processCore(package, version) {
             return file;
         }
     });
-    packageJson.main = "dist/preview release/babylon.max.js";
+    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));

+ 3 - 0
Tools/Publisher/package.json

@@ -12,5 +12,8 @@
     "fs-extra": "^5.0.0",
     "prompt": "^1.0.0",
     "shelljs": "^0.7.8"
+  },
+  "devDependencies": {
+    "gulp": "^3.9.1"
   }
 }

+ 4 - 3
Viewer/dist/basicExample.html

@@ -17,8 +17,9 @@
     </head>
 
     <body>
-        <babylon model.title="Damaged Helmet" model.subtitle="BabylonJS" model.thumbnail="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png"
-            model.url="https://www.babylonjs.com/Assets/DamagedHelmet/glTF/DamagedHelmet.gltf" camera.behaviors.auto-rotate="0" templates.nav-bar.params.disable-on-fullscreen="true"></babylon>
+        <babylon configuration="config.json" model.title="Damaged Helmet" model.subtitle="BabylonJS" model.thumbnail="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png"
+            model.url="https://www.babylonjs.com/Assets/DamagedHelmet/glTF/DamagedHelmet.gltf" camera.behaviors.auto-rotate="0"
+            templates.nav-bar.params.disable-on-fullscreen="true"></babylon>
         <script src="viewer.js"></script>
         <script>
             // The following lines are redundant. 
@@ -31,4 +32,4 @@
         </script>
     </body>
 
-</html>
+</html>

+ 5 - 0
Viewer/dist/config.json

@@ -0,0 +1,5 @@
+{
+    "scene": {
+        "debug": false
+    }
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 18444 - 15388
Viewer/dist/viewer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
Viewer/dist/viewer.min.js


+ 10 - 10
Viewer/package.json

@@ -23,21 +23,21 @@
     },
     "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
     "devDependencies": {
-        "@types/node": "^8.0.53",
-        "base64-image-loader": "^1.2.0",
-        "html-loader": "^0.5.1",
+        "@types/node": "^8.5.8",
+        "base64-image-loader": "^1.2.1",
+        "html-loader": "^0.5.4",
         "json-loader": "^0.5.7",
         "ts-loader": "^2.3.7",
         "typescript": "^2.6.2",
-        "uglifyjs-webpack-plugin": "^1.1.1",
-        "webpack": "^3.8.1",
-        "webpack-dev-server": "^2.9.5"
+        "uglifyjs-webpack-plugin": "^1.1.6",
+        "webpack": "^3.10.0",
+        "webpack-dev-server": "^2.11.0"
     },
     "dependencies": {
-        "babylonjs": "^3.1.0-beta6",
-        "babylonjs-loaders": "^3.1.0-beta6",
+        "babylonjs": "^3.2.0-alpha4",
+        "babylonjs-loaders": "^3.2.0-alpha4",
         "deepmerge": "^2.0.1",
-        "es6-promise": "^4.1.1",
+        "es6-promise": "^4.2.2",
         "handlebars": "^4.0.11"
     }
-}
+}

+ 5 - 15
Viewer/src/configuration/configuration.ts

@@ -9,24 +9,11 @@ export interface ViewerConfiguration {
     pageUrl?: string; // will be used for sharing and other fun stuff. This is the page showing the model (not the model's url!)
 
     configuration?: string | {
-        url: string;
+        url?: string;
+        payload?: any;
         mapper?: string; // json (default), html, yaml, xml, etc'. if not provided, file extension will be used.
     };
 
-    // Deprecated
-    /*// native (!!!) javascript events. Mainly used in the JSON-format.
-    // those events will be triggered by the container element (the <babylon> tag);
-    events?: {
-        load: boolean | string;
-        init: boolean | string;
-        meshselected: boolean | string;
-        pointerdown: boolean | string;
-        pointerup: boolean | string;
-        pointermove: boolean | string;
-        // load: 'onViewerLoaded' // will trigger the event prefix-onViewerLoaded instead of prefix-onLoad (and ONLY this event).
-    } | boolean; //events: true - fire all events*/
-    //eventPrefix?: string;
-
     // names of functions in the window context.
     observers?: {
         onEngineInit?: string;
@@ -137,6 +124,9 @@ export interface ViewerConfiguration {
     // engine configuration. optional!
     engine?: {
         antialiasing?: boolean;
+        disableResize?: boolean;
+        engineOptions?: { [key: string]: any };
+        adaptiveQuality?: boolean;
     },
     //templateStructure?: ITemplateStructure,
     templates?: {

+ 28 - 17
Viewer/src/configuration/loader.ts

@@ -6,7 +6,11 @@ import * as deepmerge from '../../assets/deepmerge.min.js';
 
 export class ConfigurationLoader {
 
-    private configurationCache: { (url: string): any };
+    private configurationCache: { [url: string]: any };
+
+    constructor() {
+        this.configurationCache = {};
+    }
 
     public loadConfiguration(initConfig: ViewerConfiguration = {}): Promise<ViewerConfiguration> {
 
@@ -19,20 +23,27 @@ export class ConfigurationLoader {
         if (loadedConfig.configuration) {
 
             let mapperType = "json";
-            let url = loadedConfig.configuration;
-
-            // if configuration is an object
-            if (loadedConfig.configuration.url) {
-                url = loadedConfig.configuration.url;
-                mapperType = loadedConfig.configuration.mapper;
-                if (!mapperType) {
-                    // load mapper type from filename / url
-                    mapperType = loadedConfig.configuration.url.split('.').pop();
+            return Promise.resolve().then(() => {
+                if (typeof loadedConfig.configuration === "string" || loadedConfig.configuration.url) {
+                    // a file to load
+                    let url = loadedConfig.configuration;
+
+                    // if configuration is an object
+                    if (loadedConfig.configuration.url) {
+                        url = loadedConfig.configuration.url;
+                        mapperType = loadedConfig.configuration.mapper;
+                        if (!mapperType) {
+                            // load mapper type from filename / url
+                            mapperType = loadedConfig.configuration.url.split('.').pop();
+                        }
+                    }
+                    return this.loadFile(url);
+                } else {
+                    mapperType = loadedConfig.configuration.mapper || mapperType;
+                    return loadedConfig.configuration.payload || {};
                 }
-            }
-
-            let mapper = mapperManager.getMapper(mapperType);
-            return this.loadFile(url).then((data: any) => {
+            }).then((data: any) => {
+                let mapper = mapperManager.getMapper(mapperType);
                 let parsed = mapper.map(data);
                 return deepmerge(loadedConfig, parsed);
             });
@@ -62,10 +73,10 @@ export class ConfigurationLoader {
                     if (xhr.status === OK) {
                         cacheReference[url] = xhr.responseText;
                         resolve(xhr.responseText); // 'This is the returned text.'
+                    } else {
+                        console.log('Error: ' + xhr.status, url);
+                        reject('Error: ' + xhr.status); // An error occurred during the request.
                     }
-                } else {
-                    console.log('Error: ' + xhr.status, url);
-                    reject('Error: ' + xhr.status); // An error occurred during the request.
                 }
             }
         });

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

@@ -117,5 +117,4 @@ export class MapperManager {
 
 }
 
-export let mapperManager = new MapperManager();
-export default mapperManager;
+export let mapperManager = new MapperManager();

+ 7 - 1
Viewer/src/configuration/types/default.ts

@@ -17,6 +17,11 @@ export let defaultConfiguration: ViewerConfiguration = {
         },
         viewer: {
             html: require("../../../assets/templates/default/defaultViewer.html"),
+            events: {
+                pointerout: true,
+                pointerdown: true,
+                pointerup: true
+            }
         },
         navBar: {
             html: require("../../../assets/templates/default/navbar.html"),
@@ -34,7 +39,8 @@ export let defaultConfiguration: ViewerConfiguration = {
                 visibilityTimeout: 2000
             },
             events: {
-                pointerdown: { 'fullscreen-button': true/*, '#help-button': true*/ }
+                pointerdown: { 'fullscreen-button': true/*, '#help-button': true*/ },
+                pointerover: true
             }
         },
         overlay: {

+ 2 - 1
Viewer/src/configuration/types/index.ts

@@ -1,7 +1,8 @@
 import { minimalConfiguration } from './minimal';
 import { defaultConfiguration } from './default';
+import { ViewerConfiguration } from '../configuration';
 
-let getConfigurationType = function (type: string) {
+let getConfigurationType = function (type: string): ViewerConfiguration {
     switch (type) {
         case 'default':
             return defaultConfiguration;

+ 40 - 0
Viewer/src/eventManager.ts

@@ -0,0 +1,40 @@
+import { EventCallback, TemplateManager } from "./templateManager";
+
+
+export class EventManager {
+
+    private callbacksContainer: { [key: string]: Array<{ eventType?: string, selector?: string, callback: (eventData: EventCallback) => void }> }
+
+    constructor(private templateManager: TemplateManager) {
+        this.callbacksContainer = {};
+        this.templateManager.onEventTriggered.add(eventData => {
+            this.eventTriggered(eventData);
+        })
+    }
+
+    public registerCallback(templateName: string, callback: (eventData: EventCallback) => void, eventType?: string, selector?: string) {
+        if (!this.callbacksContainer[templateName]) {
+            this.callbacksContainer[templateName] = [];
+        }
+        this.callbacksContainer[templateName].push({
+            eventType: eventType,
+            callback: callback
+        });
+    }
+
+    public unregisterCallback(templateName: string, callback?: (eventData: EventCallback) => void, eventType?: string, selector?: string) {
+        let callbackDefs = this.callbacksContainer[templateName] || [];
+        this.callbacksContainer[templateName] = callbackDefs.filter(callbackDef => (!callbackDef.eventType || callbackDef.eventType === eventType) && (!callbackDef.selector || callbackDef.selector === selector));
+    }
+
+    private eventTriggered(data: EventCallback) {
+        let templateName = data.template.name;
+        let eventType = data.event.type;
+        let selector = data.selector;
+
+        let callbackDefs = this.callbacksContainer[templateName] || [];
+        callbackDefs.filter(callbackDef => (!callbackDef.eventType || callbackDef.eventType === eventType) && (!callbackDef.selector || callbackDef.selector === selector)).forEach(callbackDef => {
+            callbackDef.callback(data);
+        });
+    }
+}

+ 60 - 23
Viewer/src/templateManager.ts

@@ -40,6 +40,9 @@ export class TemplateManager {
     public onLoaded: Observable<Template>;
     public onStateChange: Observable<Template>;
     public onAllLoaded: Observable<TemplateManager>;
+    public onEventTriggered: Observable<EventCallback>;
+
+    public eventManager: EventManager;
 
     private templates: { [name: string]: Template };
 
@@ -50,6 +53,9 @@ export class TemplateManager {
         this.onLoaded = new Observable<Template>();
         this.onStateChange = new Observable<Template>();
         this.onAllLoaded = new Observable<TemplateManager>();
+        this.onEventTriggered = new Observable<EventCallback>();
+
+        this.eventManager = new EventManager(this);
     }
 
     public initTemplate(templates: { [key: string]: ITemplateConfiguration }) {
@@ -83,8 +89,13 @@ export class TemplateManager {
         }
 
         //build the html tree
-        this.buildHTMLTree(templates).then(htmlTree => {
-            internalInit(htmlTree, 'main');
+        return this.buildHTMLTree(templates).then(htmlTree => {
+            if (this.templates['main']) {
+                internalInit(htmlTree, 'main');
+            } else {
+                this.checkLoadedState();
+            }
+            return;
         });
     }
 
@@ -101,6 +112,8 @@ export class TemplateManager {
     private buildHTMLTree(templates: { [key: string]: ITemplateConfiguration }): Promise<object> {
         let promises = Object.keys(templates).map(name => {
             let template = new Template(name, templates[name]);
+            // make sure the global onEventTriggered is called as well
+            template.onEventTriggered.add(eventData => this.onEventTriggered.notifyObservers(eventData));
             this.templates[name] = template;
             return template.initPromise;
         });
@@ -115,8 +128,9 @@ export class TemplateManager {
                     buildTree(parentObject[element], element);
                 });
             }
-
-            buildTree(templateStructure, "main");
+            if (this.templates['main']) {
+                buildTree(templateStructure, "main");
+            }
             return templateStructure;
         });
     }
@@ -131,7 +145,7 @@ export class TemplateManager {
     }
 
     private checkLoadedState() {
-        let done = Object.keys(this.templates).every((key) => {
+        let done = Object.keys(this.templates).length === 0 || Object.keys(this.templates).every((key) => {
             return this.templates[key].isLoaded && !!this.templates[key].parent;
         });
 
@@ -144,6 +158,8 @@ export class TemplateManager {
 
 
 import * as Handlebars from '../assets/handlebars.min.js';
+import { PromiseObservable } from './util/promiseObservable';
+import { EventManager } from './eventManager';
 // register a new helper. modified https://stackoverflow.com/questions/9838925/is-there-any-method-to-iterate-a-map-with-handlebars-js
 Handlebars.registerHelper('eachInMap', function (map, block) {
     var out = '';
@@ -168,6 +184,11 @@ export class Template {
     public onEventTriggered: Observable<EventCallback>;
 
     public isLoaded: boolean;
+    /**
+     * This is meant to be used to track the show and hide functions.
+     * This is NOT (!!) a flag to check if the element is actually visible to the user.
+     */
+    public isShown: boolean;
 
     public parent: HTMLElement;
 
@@ -183,6 +204,7 @@ export class Template {
         this.onEventTriggered = new Observable<EventCallback>();
 
         this.isLoaded = false;
+        this.isShown = false;
         /*
         if (configuration.id) {
             this.parent.id = configuration.id;
@@ -199,6 +221,7 @@ export class Template {
                 let rawHtml = compiledTemplate(config);
                 this.fragment = document.createRange().createContextualFragment(rawHtml);
                 this.isLoaded = true;
+                this.isShown = true;
                 this.onLoaded.notifyObservers(this);
             }
             return this;
@@ -243,30 +266,44 @@ export class Template {
     }
 
     public show(visibilityFunction?: (template: Template) => Promise<Template>): Promise<Template> {
-        if (visibilityFunction) {
-            return visibilityFunction(this).then(() => {
-                this.onStateChange.notifyObservers(this);
+        return Promise.resolve().then(() => {
+            if (visibilityFunction) {
+                return visibilityFunction(this);
+            } else {
+                // flex? box? should this be configurable easier than the visibilityFunction?
+                this.parent.style.display = 'flex';
                 return this;
-            });
-        } else {
-            // flex? box? should this be configurable easier than the visibilityFunction?
-            this.parent.style.display = 'flex';
+            }
+        }).then(() => {
+            this.isShown = true;
             this.onStateChange.notifyObservers(this);
-            return Promise.resolve(this);
-        }
+            return this;
+        });
     }
 
     public hide(visibilityFunction?: (template: Template) => Promise<Template>): Promise<Template> {
-        if (visibilityFunction) {
-            return visibilityFunction(this).then(() => {
-                this.onStateChange.notifyObservers(this);
+        return Promise.resolve().then(() => {
+            if (visibilityFunction) {
+                return visibilityFunction(this);
+            } else {
+                // flex? box? should this be configurable easier than the visibilityFunction?
+                this.parent.style.display = 'hide';
                 return this;
-            });
-        } else {
-            this.parent.style.display = 'none';
+            }
+        }).then(() => {
+            this.isShown = false;
             this.onStateChange.notifyObservers(this);
-            return Promise.resolve(this);
-        }
+            return this;
+        });
+    }
+
+    public dispose() {
+        this.onAppended.clear();
+        this.onEventTriggered.clear();
+        this.onInit.clear();
+        this.onLoaded.clear();
+        this.onStateChange.clear();
+        this.isLoaded = false;
     }
 
     // TODO - Should events be removed as well? when are templates disposed?
@@ -286,7 +323,7 @@ export class Template {
                         // strict null checl is working incorrectly, must override:
                         let event = this._configuration.events[eventName] || {};
                         selectorsArray.filter(selector => event[selector]).forEach(selector => {
-                            if (selector.indexOf('#') !== 0) {
+                            if (selector && selector.indexOf('#') !== 0) {
                                 selector = '#' + selector;
                             }
                             let htmlElement = <HTMLElement>this.parent.querySelector(selector);

+ 42 - 59
Viewer/src/viewer/defaultViewer.ts

@@ -1,7 +1,7 @@
 
 
 import { ViewerConfiguration } from './../configuration/configuration';
-import { Template } from './../templateManager';
+import { Template, EventCallback } from './../templateManager';
 import { AbstractViewer } from './viewer';
 import { MirrorTexture, Plane, ShadowGenerator, Texture, BackgroundMaterial, Observable, ShadowLight, CubeTexture, BouncingBehavior, FramingBehavior, Behavior, Light, Engine, Scene, AutoRotationBehavior, AbstractMesh, Quaternion, StandardMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
 import { CameraBehavior } from '../interfaces';
@@ -27,9 +27,22 @@ export class DefaultViewer extends AbstractViewer {
         this.showLoadingScreen();
 
         // navbar
-        let viewerElement = this.templateManager.getTemplate('viewer');
+        this.initNavbar();
+
+        // close overlay button
+        let closeButton = document.getElementById('close-button');
+        if (closeButton) {
+            closeButton.addEventListener('pointerdown', () => {
+                this.hideOverlayScreen();
+            })
+        }
+
+        return super.onTemplatesLoaded();
+    }
+
+    private initNavbar() {
         let navbar = this.templateManager.getTemplate('navBar');
-        if (viewerElement && navbar) {
+        if (navbar) {
             let navbarHeight = navbar.parent.clientHeight + 'px';
 
             let navbarShown: boolean = true;
@@ -61,64 +74,30 @@ export class DefaultViewer extends AbstractViewer {
                 }
             }
 
-
-
-            viewerElement.parent.addEventListener('pointerout', triggerNavbar.bind(this, false));
-            viewerElement.parent.addEventListener('pointerdown', triggerNavbar.bind(this, true));
-            viewerElement.parent.addEventListener('pointerup', triggerNavbar.bind(this, false));
-            navbar.parent.addEventListener('pointerover', triggerNavbar.bind(this, true))
-            // triggerNavbar(false);
-
-            // events registration
-            this.registerNavbarButtons();
-        }
-
-        // close overlay button
-        let closeButton = document.getElementById('close-button');
-        if (closeButton) {
-            closeButton.addEventListener('pointerdown', () => {
-                this.hideOverlayScreen();
-            })
-        }
-
-        return super.onTemplatesLoaded();
-    }
-
-    private registerNavbarButtons() {
-        let isFullscreen = false;
-
-        let navbar = this.templateManager.getTemplate('navBar');
-        let viewerTemplate = this.templateManager.getTemplate('viewer');
-        if (!navbar || !viewerTemplate) return;
-
-        let viewerElement = viewerTemplate.parent;
-
-
-        navbar.onEventTriggered.add((data) => {
-            switch (data.event.type) {
-                case 'pointerdown':
-                    let event: PointerEvent = <PointerEvent>data.event;
-                    if (event.button === 0) {
-                        switch (data.selector) {
-                            case '#fullscreen-button':
-                                if (!isFullscreen) {
-                                    let requestFullScreen = viewerElement.requestFullscreen || viewerElement.webkitRequestFullscreen || (<any>viewerElement).msRequestFullscreen || (<any>viewerElement).mozRequestFullScreen;
-                                    requestFullScreen.call(viewerElement);
-                                } else {
-                                    let exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || (<any>document).msExitFullscreen || (<any>document).mozCancelFullScreen
-                                    exitFullscreen.call(document);
-                                }
-
-                                isFullscreen = !isFullscreen;
-                                break;
-                            case '#help-button':
-                                this.showOverlayScreen('help');
-                                break;
-                        }
+            this.templateManager.eventManager.registerCallback('viewer', triggerNavbar.bind(this, false), 'pointerout');
+            this.templateManager.eventManager.registerCallback('viewer', triggerNavbar.bind(this, true), 'pointerdown');
+            this.templateManager.eventManager.registerCallback('viewer', triggerNavbar.bind(this, false), 'pointerup');
+            this.templateManager.eventManager.registerCallback('navBar', triggerNavbar.bind(this, true), 'pointerover');
+
+            // other events
+            let viewerTemplate = this.templateManager.getTemplate('viewer');
+            let viewerElement = viewerTemplate && viewerTemplate.parent;
+            // full screen
+            let triggerFullscren = (eventData: EventCallback) => {
+                if (viewerElement) {
+                    let fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || (<any>document).mozFullScreenElement || (<any>document).msFullscreenElement;
+                    if (!fullscreenElement) {
+                        let requestFullScreen = viewerElement.requestFullscreen || viewerElement.webkitRequestFullscreen || (<any>viewerElement).msRequestFullscreen || (<any>viewerElement).mozRequestFullScreen;
+                        requestFullScreen.call(viewerElement);
+                    } else {
+                        let exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || (<any>document).msExitFullscreen || (<any>document).mozCancelFullScreen
+                        exitFullscreen.call(document);
                     }
-                    break;
+                }
             }
-        });
+
+            this.templateManager.eventManager.registerCallback('navBar', triggerFullscren, 'pointerdown', '#fullscreen-button');
+        }
     }
 
     protected prepareContainerElement() {
@@ -228,6 +207,10 @@ export class DefaultViewer extends AbstractViewer {
             ground.rotation.x = Math.PI / 2; // Face up by default.
             ground.receiveShadows = groundConfig.receiveShadows || false;
 
+            // position the ground correctly
+            let groundPosition = focusMeshes[0].getHierarchyBoundingVectors().min.y;
+            ground.position.y = groundPosition;
+
             // default values
             backgroundMaterial.alpha = 0.9;
             backgroundMaterial.alphaMode = Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;

+ 47 - 10
Viewer/src/viewer/viewer.ts

@@ -20,6 +20,8 @@ export abstract class AbstractViewer {
     public onEngineInitObservable: PromiseObservable<Engine>;
     public onModelLoadedObservable: PromiseObservable<AbstractMesh[]>;
 
+    private canvas: HTMLCanvasElement;
+
     constructor(public containerElement: HTMLElement, initialConfiguration: ViewerConfiguration = {}) {
         // if exists, use the container id. otherwise, generate a random string.
         if (containerElement.id) {
@@ -62,6 +64,10 @@ export abstract class AbstractViewer {
             this.templateManager.initTemplate(templateConfiguration);
             // when done, execute onTemplatesLoaded()
             this.templateManager.onAllLoaded.add(() => {
+                let canvas = this.templateManager.getCanvas();
+                if (canvas) {
+                    this.canvas = canvas;
+                }
                 this.onTemplatesLoaded();
             });
         });
@@ -72,6 +78,31 @@ export abstract class AbstractViewer {
         return this.baseId;
     }
 
+    public isCanvasInDOM(): boolean {
+        return !!this.canvas && !!this.canvas.parentElement;
+    }
+
+    protected resize = (): void => {
+        // Only resize if Canvas is in the DOM
+        if (!this.isCanvasInDOM()) {
+            return;
+        }
+
+        if (this.canvas.clientWidth <= 0 || this.canvas.clientHeight <= 0) {
+            return;
+        }
+
+        this.engine.resize();
+    }
+
+    protected render = (): void => {
+        this.scene && this.scene.render();
+    }
+
+    public dispose() {
+        window.removeEventListener('resize', this.resize);
+    }
+
     protected abstract prepareContainerElement();
 
     /**
@@ -84,7 +115,11 @@ export abstract class AbstractViewer {
      */
     protected onTemplatesLoaded(): Promise<AbstractViewer> {
         return this.initEngine().then(() => {
-            return this.loadModel();
+            if (this.configuration.model) {
+                return this.loadModel();
+            } else {
+                return this.scene;
+            }
         }).then(() => {
             return this;
         });
@@ -104,21 +139,22 @@ export abstract class AbstractViewer {
         }
         let config = this.configuration.engine || {};
         // TDO enable further configuration
-        this.engine = new Engine(canvasElement, !!config.antialiasing);
+        this.engine = new Engine(canvasElement, !!config.antialiasing, config.engineOptions);
 
         // Disable manifest checking
         Database.IDBStorageEnabled = false;
 
-        window.addEventListener('resize', () => {
-            this.engine.resize();
-        });
+        if (!config.disableResize) {
+            window.addEventListener('resize', this.resize);
+        }
 
-        this.engine.runRenderLoop(() => {
-            this.scene && this.scene.render();
-        });
 
-        var scale = Math.max(0.5, 1 / (window.devicePixelRatio || 2));
-        this.engine.setHardwareScalingLevel(scale);
+        this.engine.runRenderLoop(this.render);
+
+        if (this.configuration.engine && this.configuration.engine.adaptiveQuality) {
+            var scale = Math.max(0.5, 1 / (window.devicePixelRatio || 2));
+            this.engine.setHardwareScalingLevel(scale);
+        }
 
         return this.onEngineInitObservable.notifyWithPromise(this.engine).then(() => {
             return this.engine;
@@ -145,6 +181,7 @@ export abstract class AbstractViewer {
     }
 
     public loadModel(model: any = this.configuration.model, clearScene: boolean = true): Promise<Scene> {
+        this.configuration.model = model;
         let modelUrl = (typeof model === 'string') ? model : model.url;
         let parts = modelUrl.split('/');
         let filename = parts.pop();

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

@@ -3,7 +3,7 @@
 import { Observable } from 'babylonjs';
 import { AbstractViewer } from './viewer';
 
-class ViewerManager {
+export class ViewerManager {
 
     private viewers: { [key: string]: AbstractViewer };
 

+ 251 - 0
dist/babylon.glTFInterface.d.ts

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

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 11135 - 8840
dist/preview release/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 51 - 51
dist/preview release/babylon.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2553 - 467
dist/preview release/babylon.max.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 19088 - 0
dist/preview release/babylon.module.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 52 - 52
dist/preview release/babylon.worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3459 - 1169
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 55 - 55
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2499 - 468
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2501 - 470
dist/preview release/customConfigurations/minimalGLTFViewer/es6.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2555 - 469
dist/preview release/es6.js


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

@@ -56,6 +56,17 @@ declare module BABYLON.GUI {
         private _manageFocus();
         private _attachToOnPointerOut(scene);
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean): AdvancedDynamicTexture;
+        /**
+         * FullScreenUI is created in a layer. This allows it to be treated like any other layer.
+         * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
+         * When the GUI is not Created as FullscreenUI it does not respect the layerMask.
+         * layerMask is set through advancedTexture.layer.layerMask
+         * @param name name for the Texture
+         * @param foreground render in foreground (default is true)
+         * @param scene scene to be rendered in
+         * @param sampling method for scaling to fit screen
+         * @returns AdvancedDynamicTexture
+         */
         static CreateFullscreenUI(name: string, foreground?: boolean, scene?: Nullable<Scene>, sampling?: number): AdvancedDynamicTexture;
     }
 }
@@ -509,6 +520,9 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class TextBlock extends Control {
+        /**
+         * Defines the name of the control
+         */
         name: string | undefined;
         private _text;
         private _textWrapping;
@@ -522,15 +536,70 @@ declare module BABYLON.GUI {
         * @type {BABYLON.Observable}
         */
         onTextChangedObservable: Observable<TextBlock>;
+        /**
+        * An event triggered after the text was broken up into lines
+        * @type {BABYLON.Observable}
+        */
+        onLinesReadyObservable: Observable<TextBlock>;
+        /**
+         * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
+         */
+        readonly lines: any[];
+        /**
+         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+         */
+        /**
+         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+         */
         resizeToFit: boolean;
+        /**
+         * Gets or sets a boolean indicating if text must be wrapped
+         */
+        /**
+         * Gets or sets a boolean indicating if text must be wrapped
+         */
         textWrapping: boolean;
+        /**
+         * Gets or sets text to display
+         */
+        /**
+         * Gets or sets text to display
+         */
         text: string;
+        /**
+         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+         */
+        /**
+         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+         */
         textHorizontalAlignment: number;
+        /**
+         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+         */
+        /**
+         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+         */
         textVerticalAlignment: number;
+        /**
+         * Gets or sets line spacing value
+         */
+        /**
+         * Gets or sets line spacing value
+         */
         lineSpacing: string | number;
-        constructor(name?: string | undefined, text?: string);
+        /**
+         * Creates a new TextBlock object
+         * @param name defines the name of the control
+         * @param text defines the text to display (emptry string by default)
+         */
+        constructor(
+            /**
+             * Defines the name of the control
+             */
+            name?: string | undefined, text?: string);
         protected _getTypeName(): string;
         private _drawText(text, textWidth, y, context);
+        /** @ignore */
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _parseLine(line: string | undefined, context: CanvasRenderingContext2D): object;

+ 74 - 1
dist/preview release/gui/babylon.gui.js

@@ -476,6 +476,17 @@ var BABYLON;
                 result.attachToMesh(mesh, supportPointerMove);
                 return result;
             };
+            /**
+             * FullScreenUI is created in a layer. This allows it to be treated like any other layer.
+             * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
+             * When the GUI is not Created as FullscreenUI it does not respect the layerMask.
+             * layerMask is set through advancedTexture.layer.layerMask
+             * @param name name for the Texture
+             * @param foreground render in foreground (default is true)
+             * @param scene scene to be rendered in
+             * @param sampling method for scaling to fit screen
+             * @returns AdvancedDynamicTexture
+             */
             AdvancedDynamicTexture.CreateFullscreenUI = function (name, foreground, scene, sampling) {
                 if (foreground === void 0) { foreground = true; }
                 if (scene === void 0) { scene = null; }
@@ -3174,7 +3185,16 @@ var BABYLON;
     (function (GUI) {
         var TextBlock = /** @class */ (function (_super) {
             __extends(TextBlock, _super);
-            function TextBlock(name, text) {
+            /**
+             * Creates a new TextBlock object
+             * @param name defines the name of the control
+             * @param text defines the text to display (emptry string by default)
+             */
+            function TextBlock(
+                /**
+                 * Defines the name of the control
+                 */
+                name, text) {
                 if (text === void 0) { text = ""; }
                 var _this = _super.call(this, name) || this;
                 _this.name = name;
@@ -3189,13 +3209,34 @@ var BABYLON;
                 * @type {BABYLON.Observable}
                 */
                 _this.onTextChangedObservable = new BABYLON.Observable();
+                /**
+                * An event triggered after the text was broken up into lines
+                * @type {BABYLON.Observable}
+                */
+                _this.onLinesReadyObservable = new BABYLON.Observable();
                 _this.text = text;
                 return _this;
             }
+            Object.defineProperty(TextBlock.prototype, "lines", {
+                /**
+                 * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
+                 */
+                get: function () {
+                    return this._lines;
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(TextBlock.prototype, "resizeToFit", {
+                /**
+                 * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+                 */
                 get: function () {
                     return this._resizeToFit;
                 },
+                /**
+                 * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+                 */
                 set: function (value) {
                     this._resizeToFit = value;
                     if (this._resizeToFit) {
@@ -3207,9 +3248,15 @@ var BABYLON;
                 configurable: true
             });
             Object.defineProperty(TextBlock.prototype, "textWrapping", {
+                /**
+                 * Gets or sets a boolean indicating if text must be wrapped
+                 */
                 get: function () {
                     return this._textWrapping;
                 },
+                /**
+                 * Gets or sets a boolean indicating if text must be wrapped
+                 */
                 set: function (value) {
                     if (this._textWrapping === value) {
                         return;
@@ -3221,9 +3268,15 @@ var BABYLON;
                 configurable: true
             });
             Object.defineProperty(TextBlock.prototype, "text", {
+                /**
+                 * Gets or sets text to display
+                 */
                 get: function () {
                     return this._text;
                 },
+                /**
+                 * Gets or sets text to display
+                 */
                 set: function (value) {
                     if (this._text === value) {
                         return;
@@ -3236,9 +3289,15 @@ var BABYLON;
                 configurable: true
             });
             Object.defineProperty(TextBlock.prototype, "textHorizontalAlignment", {
+                /**
+                 * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+                 */
                 get: function () {
                     return this._textHorizontalAlignment;
                 },
+                /**
+                 * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+                 */
                 set: function (value) {
                     if (this._textHorizontalAlignment === value) {
                         return;
@@ -3250,9 +3309,15 @@ var BABYLON;
                 configurable: true
             });
             Object.defineProperty(TextBlock.prototype, "textVerticalAlignment", {
+                /**
+                 * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+                 */
                 get: function () {
                     return this._textVerticalAlignment;
                 },
+                /**
+                 * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+                 */
                 set: function (value) {
                     if (this._textVerticalAlignment === value) {
                         return;
@@ -3264,9 +3329,15 @@ var BABYLON;
                 configurable: true
             });
             Object.defineProperty(TextBlock.prototype, "lineSpacing", {
+                /**
+                 * Gets or sets line spacing value
+                 */
                 get: function () {
                     return this._lineSpacing.toString(this._host);
                 },
+                /**
+                 * Gets or sets line spacing value
+                 */
                 set: function (value) {
                     if (this._lineSpacing.fromString(value)) {
                         this._markAsDirty();
@@ -3300,6 +3371,7 @@ var BABYLON;
                 }
                 context.fillText(text, this._currentMeasure.left + x, y);
             };
+            /** @ignore */
             TextBlock.prototype._draw = function (parentMeasure, context) {
                 context.save();
                 this._applyStates(context);
@@ -3324,6 +3396,7 @@ var BABYLON;
                         this._lines.push(this._parseLine(_line, context));
                     }
                 }
+                this.onLinesReadyObservable.notifyObservers(this);
             };
             TextBlock.prototype._parseLine = function (line, context) {
                 if (line === void 0) { line = ''; }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
dist/preview release/gui/babylon.gui.min.js


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

@@ -62,6 +62,17 @@ declare module BABYLON.GUI {
         private _manageFocus();
         private _attachToOnPointerOut(scene);
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean): AdvancedDynamicTexture;
+        /**
+         * FullScreenUI is created in a layer. This allows it to be treated like any other layer.
+         * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
+         * When the GUI is not Created as FullscreenUI it does not respect the layerMask.
+         * layerMask is set through advancedTexture.layer.layerMask
+         * @param name name for the Texture
+         * @param foreground render in foreground (default is true)
+         * @param scene scene to be rendered in
+         * @param sampling method for scaling to fit screen
+         * @returns AdvancedDynamicTexture
+         */
         static CreateFullscreenUI(name: string, foreground?: boolean, scene?: Nullable<Scene>, sampling?: number): AdvancedDynamicTexture;
     }
 }
@@ -515,6 +526,9 @@ declare module BABYLON.GUI {
 
 declare module BABYLON.GUI {
     class TextBlock extends Control {
+        /**
+         * Defines the name of the control
+         */
         name: string | undefined;
         private _text;
         private _textWrapping;
@@ -528,15 +542,70 @@ declare module BABYLON.GUI {
         * @type {BABYLON.Observable}
         */
         onTextChangedObservable: Observable<TextBlock>;
+        /**
+        * An event triggered after the text was broken up into lines
+        * @type {BABYLON.Observable}
+        */
+        onLinesReadyObservable: Observable<TextBlock>;
+        /**
+         * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
+         */
+        readonly lines: any[];
+        /**
+         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+         */
+        /**
+         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+         */
         resizeToFit: boolean;
+        /**
+         * Gets or sets a boolean indicating if text must be wrapped
+         */
+        /**
+         * Gets or sets a boolean indicating if text must be wrapped
+         */
         textWrapping: boolean;
+        /**
+         * Gets or sets text to display
+         */
+        /**
+         * Gets or sets text to display
+         */
         text: string;
+        /**
+         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+         */
+        /**
+         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+         */
         textHorizontalAlignment: number;
+        /**
+         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+         */
+        /**
+         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+         */
         textVerticalAlignment: number;
+        /**
+         * Gets or sets line spacing value
+         */
+        /**
+         * Gets or sets line spacing value
+         */
         lineSpacing: string | number;
-        constructor(name?: string | undefined, text?: string);
+        /**
+         * Creates a new TextBlock object
+         * @param name defines the name of the control
+         * @param text defines the text to display (emptry string by default)
+         */
+        constructor(
+            /**
+             * Defines the name of the control
+             */
+            name?: string | undefined, text?: string);
         protected _getTypeName(): string;
         private _drawText(text, textWidth, y, context);
+        /** @ignore */
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _parseLine(line: string | undefined, context: CanvasRenderingContext2D): object;

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -362,7 +362,7 @@ declare module BABYLON.GLTF2 {
         index: number;
         texCoord?: number;
     }
-    interface IGLTF extends IGLTFProperty {
+    interface _IGLTF extends IGLTFProperty {
         accessors?: IGLTFAccessor[];
         animations?: IGLTFAnimation[];
         asset: IGLTFAsset;
@@ -386,7 +386,7 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2 {
     class GLTFLoader implements IGLTFLoader {
-        _gltf: IGLTF;
+        _gltf: _IGLTF;
         _babylonScene: Scene;
         private _disposed;
         private _rootUrl;

+ 0 - 3
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -1891,9 +1891,6 @@ var BABYLON;
                     });
                 });
                 this._requests.push(request);
-                request.onCompleteObservable.add(function () {
-                    _this._requests.splice(_this._requests.indexOf(request), 1);
-                });
             };
             GLTFLoader.prototype._tryCatchOnError = function (handler) {
                 if (this._disposed) {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -919,7 +919,7 @@ declare module BABYLON.GLTF2 {
         index: number;
         texCoord?: number;
     }
-    interface IGLTF extends IGLTFProperty {
+    interface _IGLTF extends IGLTFProperty {
         accessors?: IGLTFAccessor[];
         animations?: IGLTFAnimation[];
         asset: IGLTFAsset;
@@ -943,7 +943,7 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2 {
     class GLTFLoader implements IGLTFLoader {
-        _gltf: IGLTF;
+        _gltf: _IGLTF;
         _babylonScene: Scene;
         private _disposed;
         private _rootUrl;

+ 0 - 3
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -4057,9 +4057,6 @@ var BABYLON;
                     });
                 });
                 this._requests.push(request);
-                request.onCompleteObservable.add(function () {
-                    _this._requests.splice(_this._requests.indexOf(request), 1);
-                });
             };
             GLTFLoader.prototype._tryCatchOnError = function (handler) {
                 if (this._disposed) {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 0 - 3
dist/preview release/loaders/babylonjs.loaders.js

@@ -5031,9 +5031,6 @@ var BABYLON;
                     });
                 });
                 this._requests.push(request);
-                request.onCompleteObservable.add(function () {
-                    _this._requests.splice(_this._requests.indexOf(request), 1);
-                });
             };
             GLTFLoader.prototype._tryCatchOnError = function (handler) {
                 if (this._disposed) {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -1020,7 +1020,7 @@ declare module BABYLON.GLTF2 {
         index: number;
         texCoord?: number;
     }
-    interface IGLTF extends IGLTFProperty {
+    interface _IGLTF extends IGLTFProperty {
         accessors?: IGLTFAccessor[];
         animations?: IGLTFAnimation[];
         asset: IGLTFAsset;
@@ -1044,7 +1044,7 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2 {
     class GLTFLoader implements IGLTFLoader {
-        _gltf: IGLTF;
+        _gltf: _IGLTF;
         _babylonScene: Scene;
         private _disposed;
         private _rootUrl;

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

@@ -31,7 +31,5 @@
     },
     "engines": {
         "node": "*"
-    },
-    "_id": "babylonjs-loaders@3.1.0-alpha1",
-    "_from": "babylonjs-loaders@"
+    }
 }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 3
dist/preview release/materialsLibrary/babylonjs.materials.min.js


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

@@ -31,7 +31,5 @@
     },
     "engines": {
         "node": "*"
-    },
-    "_id": "babylonjs-materials@3.1.0-alpha1",
-    "_from": "babylonjs-materials@"
+    }
 }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


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

@@ -31,7 +31,5 @@
     },
     "engines": {
         "node": "*"
-    },
-    "_id": "babylonjs-post-process@3.1.0-alpha1",
-    "_from": "babylonjs-post-process@"
+    }
 }

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

@@ -31,7 +31,5 @@
     },
     "engines": {
         "node": "*"
-    },
-    "_id": "babylonjs-procedural-textures@3.1.0-alpha1",
-    "_from": "babylonjs-procedural-textures@"
+    }
 }

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

@@ -1,47 +1,118 @@
 
 declare module BABYLON {
+    /**
+     * Holds a collection of exporter options and parameters
+     */
+    interface IExporterOptions {
+        /**
+         * Function which indicates whether a babylon mesh should be exported or not.
+         * @param mesh - source Babylon mesh. It is used to check whether it should be
+         * exported to glTF or not.
+         * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
+         */
+        shouldExportMesh?(mesh: AbstractMesh): boolean;
+    }
+    /**
+     * Class for generating glTF data from a Babylon scene.
+     */
     class GLTF2Export {
         /**
-         * Exports the geometry of a Mesh array in .gltf file format.
-         * If glb is set to true, exports as .glb.
-         * @param meshes
-         * @param materials
-         *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .gltf, .glb and associates textures
+         * Exports the geometry of the scene to .gltf file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating the glTF file.
+         * @param options - Exporter options.
+         * @returns - Returns an object with a .gltf file and associates texture names
          * as keys and their data and paths as values.
          */
-        static GLTF(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLTF(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData;
         /**
-         *
-         * @param meshes
-         * @param filename
-         *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .glb filename as key and data as value
+         * Exports the geometry of the scene to .glb file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating glb file.
+         * @param options - Exporter options.
+         * @returns - Returns an object with a .glb filename as key and data as value
          */
-        static GLB(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLB(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData;
     }
 }
 
-declare module BABYLON {
-    class _GLTF2Exporter {
+
+/**
+ * Module for the Babylon glTF 2.0 exporter.  Should ONLY be used internally.
+ * @ignore - capitalization of GLTF2 module.
+ */
+declare module BABYLON.GLTF2 {
+    /**
+     * Converts Babylon Scene into glTF 2.0.
+     */
+    class _Exporter {
+        /**
+         * Stores all generated buffer views, which represents views into the main glTF buffer data.
+         */
         private bufferViews;
+        /**
+         * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF.
+         */
         private accessors;
+        /**
+         * Stores all the generated nodes, which contains transform and/or mesh information per node.
+         */
         private nodes;
+        /**
+         * Stores the glTF asset information, which represents the glTF version and this file generator.
+         */
         private asset;
+        /**
+         * Stores all the generated glTF scenes, which stores multiple node hierarchies.
+         */
         private scenes;
+        /**
+         * Stores all the generated mesh information, each containing a set of primitives to render in glTF.
+         */
         private meshes;
+        /**
+         * Stores all the generated material information, which represents the appearance of each primitive.
+         */
+        private materials;
+        /**
+         * Stores all the generated texture information, which is referenced by glTF materials.
+         */
+        private textures;
+        /**
+         * Stores all the generated image information, which is referenced by glTF textures.
+         */
+        private images;
+        /**
+         * Stores the total amount of bytes stored in the glTF buffer.
+         */
         private totalByteLength;
+        /**
+         * Stores a reference to the Babylon scene containing the source geometry and material information.
+         */
         private babylonScene;
-        constructor(babylonScene: BABYLON.Scene);
+        /**
+         * Stores the exporter options, which are optionally passed in from the glTF serializer.
+         */
+        private options?;
+        /**
+         * Stores a map of the image data, where the key is the file name and the value
+         * is the image data.
+         */
+        private imageData;
+        /**
+         * Creates a glTF Exporter instance, which can accept optional exporter options.
+         * @param babylonScene - Babylon scene object
+         * @param options - Options to modify the behavior of the exporter.
+         */
+        constructor(babylonScene: Scene, options?: IExporterOptions);
         /**
          * Creates a buffer view based on teh supplied arguments
-         * @param bufferIndex
-         * @param byteOffset
-         * @param byteLength
-         *
-         * @returns {_IGLTFBufferView}
+         * @param {number} bufferIndex - index value of the specified buffer
+         * @param {number} byteOffset - byte offset value
+         * @param {number} byteLength - byte length of the bufferView
+         * @returns - bufferView for glTF
          */
-        private createBufferView(bufferIndex, byteOffset, byteLength);
+        private createBufferView(bufferIndex, byteOffset, byteLength, name?);
         /**
          * Creates an accessor based on the supplied arguments
          * @param bufferviewIndex
@@ -51,8 +122,7 @@ declare module BABYLON {
          * @param count
          * @param min
          * @param max
-         *
-         * @returns {_IGLTFAccessor}
+         * @returns - accessor for glTF
          */
         private createAccessor(bufferviewIndex, name, type, componentType, count, min?, max?);
         /**
@@ -62,8 +132,7 @@ declare module BABYLON {
          * @param vertexCount
          * @param arrayOffset
          * @param stride
-         *
-         * @returns {min: number[], max: number[]} min number array and max number array
+         * @returns - min number array and max number array
          */
         private calculateMinMax(buff, vertexStart, vertexCount, arrayOffset, stride);
         /**
@@ -76,8 +145,7 @@ declare module BABYLON {
          * @param byteOffset
          * @param dataBuffer
          * @param useRightHandedSystem
-         *
-         * @returns {number} byte length
+         * @returns - byte length
          */
         private writeAttributeData(vertexBufferType, submesh, meshAttributeArray, strideSize, byteOffset, dataBuffer, useRightHandedSystem);
         /**
@@ -85,32 +153,34 @@ declare module BABYLON {
          * @param glb
          * @param glTFPrefix
          * @param prettyPrint
-         *
-         * @returns {string} json data as string
+         * @returns - json data as string
          */
         private generateJSON(glb, glTFPrefix?, prettyPrint?);
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix
-         *
-         * @returns {[x: string]: string | Blob} object with glTF json tex filename
+         * @returns - object with glTF json tex filename
          * and binary file name as keys and their data as values
          */
         _generateGLTF(glTFPrefix: string): _GLTFData;
         /**
          * Creates a binary buffer for glTF
-         *
-         * @returns {ArrayBuffer}
+         * @returns - array buffer for binary data
          */
         private generateBinary();
         /**
+         * Pads the number to a power of 4
+         * @param num - number to pad
+         * @returns - padded number
+         */
+        private _getPadding(num);
+        /**
          * Generates a glb file from the json and binary data.
          * Returns an object with the glb file name as the key and data as the value.
          * @param jsonText
          * @param binaryBuffer
          * @param glTFPrefix
-         *
-         * @returns {[glbFileName: string]: Blob} object with glb filename as key and data as value
+         * @returns - object with glb filename as key and data as value
          */
         _generateGLB(glTFPrefix: string): _GLTFData;
         /**
@@ -121,14 +191,19 @@ declare module BABYLON {
          */
         private setNodeTransformation(node, babylonMesh, useRightHandedSystem);
         /**
+         *
+         * @param babylonTexture
+         * @return - glTF texture, or null if the texture format is not supported
+         */
+        private exportTexture(babylonTexture, mimeType?);
+        /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh
          * @param babylonMesh
          * @param byteOffset
          * @param useRightHandedSystem
          * @param dataBuffer
-         *
-         * @returns {number} bytelength of the primitive attributes plus the passed in byteOffset
+         * @returns - bytelength of the primitive attributes plus the passed in byteOffset
          */
         private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer?);
         /**
@@ -138,25 +213,81 @@ declare module BABYLON {
          * @param byteOffset
          * @param buffer
          * @param dataBuffer
-         *
-         * @returns {number} bytelength + byteoffset
+         * @returns bytelength + byteoffset
          */
         private createScene(babylonScene, byteOffset, dataBuffer?);
     }
 }
 
+
 declare module BABYLON {
     /**
      * Class for holding and downloading glTF file data
      */
     class _GLTFData {
-        _glTFFiles: {
+        /**
+         * Object which contains the file name as the key and its data as the value.
+         */
+        glTFFiles: {
             [fileName: string]: string | Blob;
         };
+        /**
+         * Initializes the glTF file object.
+         */
         constructor();
         /**
-         * Downloads glTF data.
+         * Downloads the glTF data as files based on their names and data.
          */
         downloadFiles(): void;
     }
 }
+
+
+declare module BABYLON.GLTF2 {
+    /**
+     * Utility methods for working with glTF material conversion properties.  This class should only be used internally.
+     */
+    class _GLTFMaterial {
+        /**
+         * Represents the dielectric specular values for R, G and B.
+         */
+        private static readonly dielectricSpecular;
+        /**
+         * Epsilon value, used as a small tolerance value for a numeric value.
+         */
+        private static readonly epsilon;
+        /**
+         * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
+         * @param babylonStandardMaterial
+         * @returns - glTF Metallic Roughness Material representation
+         */
+        static ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
+        /**
+         * Converts Specular Glossiness to Metallic Roughness.  This is based on the algorithm used in the Babylon glTF 3ds Max Exporter.
+         * {@link https://github.com/BabylonJS/Exporters/blob/master/3ds%20Max/Max2Babylon/Exporter/BabylonExporter.GLTFExporter.Material.cs}
+         * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
+         * @returns - Babylon metallic roughness values
+         */
+        private static _ConvertToMetallicRoughness(babylonSpecularGlossiness);
+        /**
+         * Returns the perceived brightness value based on the provided color
+         * @param color - color used in calculating the perceived brightness
+         * @returns - perceived brightness value
+         */
+        private static PerceivedBrightness(color);
+        /**
+         * Computes the metallic factor
+         * @param diffuse - diffused value
+         * @param specular - specular value
+         * @param oneMinusSpecularStrength - one minus the specular strength
+         * @returns - metallic value
+         */
+        static SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
+        /**
+         * Gets the glTF alpha mode from the Babylon Material
+         * @param babylonMaterial - Babylon Material
+         * @returns - The Babylon alpha mode value
+         */
+        static GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
+    }
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 997 - 559
dist/preview release/serializers/babylon.glTF2Serializer.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/serializers/babylon.glTF2Serializer.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 997 - 559
dist/preview release/serializers/babylonjs.serializers.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 173 - 42
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -14,48 +14,119 @@ declare module BABYLON {
 
 
 declare module BABYLON {
+    /**
+     * Holds a collection of exporter options and parameters
+     */
+    interface IExporterOptions {
+        /**
+         * Function which indicates whether a babylon mesh should be exported or not.
+         * @param mesh - source Babylon mesh. It is used to check whether it should be
+         * exported to glTF or not.
+         * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
+         */
+        shouldExportMesh?(mesh: AbstractMesh): boolean;
+    }
+    /**
+     * Class for generating glTF data from a Babylon scene.
+     */
     class GLTF2Export {
         /**
-         * Exports the geometry of a Mesh array in .gltf file format.
-         * If glb is set to true, exports as .glb.
-         * @param meshes
-         * @param materials
-         *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .gltf, .glb and associates textures
+         * Exports the geometry of the scene to .gltf file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating the glTF file.
+         * @param options - Exporter options.
+         * @returns - Returns an object with a .gltf file and associates texture names
          * as keys and their data and paths as values.
          */
-        static GLTF(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLTF(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData;
         /**
-         *
-         * @param meshes
-         * @param filename
-         *
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .glb filename as key and data as value
+         * Exports the geometry of the scene to .glb file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating glb file.
+         * @param options - Exporter options.
+         * @returns - Returns an object with a .glb filename as key and data as value
          */
-        static GLB(scene: BABYLON.Scene, filename: string): _GLTFData;
+        static GLB(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData;
     }
 }
 
-declare module BABYLON {
-    class _GLTF2Exporter {
+
+/**
+ * Module for the Babylon glTF 2.0 exporter.  Should ONLY be used internally.
+ * @ignore - capitalization of GLTF2 module.
+ */
+declare module BABYLON.GLTF2 {
+    /**
+     * Converts Babylon Scene into glTF 2.0.
+     */
+    class _Exporter {
+        /**
+         * Stores all generated buffer views, which represents views into the main glTF buffer data.
+         */
         private bufferViews;
+        /**
+         * Stores all the generated accessors, which is used for accessing the data within the buffer views in glTF.
+         */
         private accessors;
+        /**
+         * Stores all the generated nodes, which contains transform and/or mesh information per node.
+         */
         private nodes;
+        /**
+         * Stores the glTF asset information, which represents the glTF version and this file generator.
+         */
         private asset;
+        /**
+         * Stores all the generated glTF scenes, which stores multiple node hierarchies.
+         */
         private scenes;
+        /**
+         * Stores all the generated mesh information, each containing a set of primitives to render in glTF.
+         */
         private meshes;
+        /**
+         * Stores all the generated material information, which represents the appearance of each primitive.
+         */
+        private materials;
+        /**
+         * Stores all the generated texture information, which is referenced by glTF materials.
+         */
+        private textures;
+        /**
+         * Stores all the generated image information, which is referenced by glTF textures.
+         */
+        private images;
+        /**
+         * Stores the total amount of bytes stored in the glTF buffer.
+         */
         private totalByteLength;
+        /**
+         * Stores a reference to the Babylon scene containing the source geometry and material information.
+         */
         private babylonScene;
-        constructor(babylonScene: BABYLON.Scene);
+        /**
+         * Stores the exporter options, which are optionally passed in from the glTF serializer.
+         */
+        private options?;
+        /**
+         * Stores a map of the image data, where the key is the file name and the value
+         * is the image data.
+         */
+        private imageData;
+        /**
+         * Creates a glTF Exporter instance, which can accept optional exporter options.
+         * @param babylonScene - Babylon scene object
+         * @param options - Options to modify the behavior of the exporter.
+         */
+        constructor(babylonScene: Scene, options?: IExporterOptions);
         /**
          * Creates a buffer view based on teh supplied arguments
-         * @param bufferIndex
-         * @param byteOffset
-         * @param byteLength
-         *
-         * @returns {_IGLTFBufferView}
+         * @param {number} bufferIndex - index value of the specified buffer
+         * @param {number} byteOffset - byte offset value
+         * @param {number} byteLength - byte length of the bufferView
+         * @returns - bufferView for glTF
          */
-        private createBufferView(bufferIndex, byteOffset, byteLength);
+        private createBufferView(bufferIndex, byteOffset, byteLength, name?);
         /**
          * Creates an accessor based on the supplied arguments
          * @param bufferviewIndex
@@ -65,8 +136,7 @@ declare module BABYLON {
          * @param count
          * @param min
          * @param max
-         *
-         * @returns {_IGLTFAccessor}
+         * @returns - accessor for glTF
          */
         private createAccessor(bufferviewIndex, name, type, componentType, count, min?, max?);
         /**
@@ -76,8 +146,7 @@ declare module BABYLON {
          * @param vertexCount
          * @param arrayOffset
          * @param stride
-         *
-         * @returns {min: number[], max: number[]} min number array and max number array
+         * @returns - min number array and max number array
          */
         private calculateMinMax(buff, vertexStart, vertexCount, arrayOffset, stride);
         /**
@@ -90,8 +159,7 @@ declare module BABYLON {
          * @param byteOffset
          * @param dataBuffer
          * @param useRightHandedSystem
-         *
-         * @returns {number} byte length
+         * @returns - byte length
          */
         private writeAttributeData(vertexBufferType, submesh, meshAttributeArray, strideSize, byteOffset, dataBuffer, useRightHandedSystem);
         /**
@@ -99,32 +167,34 @@ declare module BABYLON {
          * @param glb
          * @param glTFPrefix
          * @param prettyPrint
-         *
-         * @returns {string} json data as string
+         * @returns - json data as string
          */
         private generateJSON(glb, glTFPrefix?, prettyPrint?);
         /**
          * Generates data for .gltf and .bin files based on the glTF prefix string
          * @param glTFPrefix
-         *
-         * @returns {[x: string]: string | Blob} object with glTF json tex filename
+         * @returns - object with glTF json tex filename
          * and binary file name as keys and their data as values
          */
         _generateGLTF(glTFPrefix: string): _GLTFData;
         /**
          * Creates a binary buffer for glTF
-         *
-         * @returns {ArrayBuffer}
+         * @returns - array buffer for binary data
          */
         private generateBinary();
         /**
+         * Pads the number to a power of 4
+         * @param num - number to pad
+         * @returns - padded number
+         */
+        private _getPadding(num);
+        /**
          * Generates a glb file from the json and binary data.
          * Returns an object with the glb file name as the key and data as the value.
          * @param jsonText
          * @param binaryBuffer
          * @param glTFPrefix
-         *
-         * @returns {[glbFileName: string]: Blob} object with glb filename as key and data as value
+         * @returns - object with glb filename as key and data as value
          */
         _generateGLB(glTFPrefix: string): _GLTFData;
         /**
@@ -135,14 +205,19 @@ declare module BABYLON {
          */
         private setNodeTransformation(node, babylonMesh, useRightHandedSystem);
         /**
+         *
+         * @param babylonTexture
+         * @return - glTF texture, or null if the texture format is not supported
+         */
+        private exportTexture(babylonTexture, mimeType?);
+        /**
          * Sets data for the primitive attributes of each submesh
          * @param mesh
          * @param babylonMesh
          * @param byteOffset
          * @param useRightHandedSystem
          * @param dataBuffer
-         *
-         * @returns {number} bytelength of the primitive attributes plus the passed in byteOffset
+         * @returns - bytelength of the primitive attributes plus the passed in byteOffset
          */
         private setPrimitiveAttributes(mesh, babylonMesh, byteOffset, useRightHandedSystem, dataBuffer?);
         /**
@@ -152,25 +227,81 @@ declare module BABYLON {
          * @param byteOffset
          * @param buffer
          * @param dataBuffer
-         *
-         * @returns {number} bytelength + byteoffset
+         * @returns bytelength + byteoffset
          */
         private createScene(babylonScene, byteOffset, dataBuffer?);
     }
 }
 
+
 declare module BABYLON {
     /**
      * Class for holding and downloading glTF file data
      */
     class _GLTFData {
-        _glTFFiles: {
+        /**
+         * Object which contains the file name as the key and its data as the value.
+         */
+        glTFFiles: {
             [fileName: string]: string | Blob;
         };
+        /**
+         * Initializes the glTF file object.
+         */
         constructor();
         /**
-         * Downloads glTF data.
+         * Downloads the glTF data as files based on their names and data.
          */
         downloadFiles(): void;
     }
 }
+
+
+declare module BABYLON.GLTF2 {
+    /**
+     * Utility methods for working with glTF material conversion properties.  This class should only be used internally.
+     */
+    class _GLTFMaterial {
+        /**
+         * Represents the dielectric specular values for R, G and B.
+         */
+        private static readonly dielectricSpecular;
+        /**
+         * Epsilon value, used as a small tolerance value for a numeric value.
+         */
+        private static readonly epsilon;
+        /**
+         * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
+         * @param babylonStandardMaterial
+         * @returns - glTF Metallic Roughness Material representation
+         */
+        static ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness;
+        /**
+         * Converts Specular Glossiness to Metallic Roughness.  This is based on the algorithm used in the Babylon glTF 3ds Max Exporter.
+         * {@link https://github.com/BabylonJS/Exporters/blob/master/3ds%20Max/Max2Babylon/Exporter/BabylonExporter.GLTFExporter.Material.cs}
+         * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
+         * @returns - Babylon metallic roughness values
+         */
+        private static _ConvertToMetallicRoughness(babylonSpecularGlossiness);
+        /**
+         * Returns the perceived brightness value based on the provided color
+         * @param color - color used in calculating the perceived brightness
+         * @returns - perceived brightness value
+         */
+        private static PerceivedBrightness(color);
+        /**
+         * Computes the metallic factor
+         * @param diffuse - diffused value
+         * @param specular - specular value
+         * @param oneMinusSpecularStrength - one minus the specular strength
+         * @returns - metallic value
+         */
+        static SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number;
+        /**
+         * Gets the glTF alpha mode from the Babylon Material
+         * @param babylonMaterial - Babylon Material
+         * @returns - The Babylon alpha mode value
+         */
+        static GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode;
+    }
+}

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

@@ -31,7 +31,5 @@
     },
     "engines": {
         "node": "*"
-    },
-    "_id": "babylonjs-serializers@3.1.0-alpha1",
-    "_from": "babylonjs-serializers@"
+    }
 }

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 4033 - 16203
dist/preview release/typedocValidationBaseline.json


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 65 - 65
dist/preview release/viewer/babylon.viewer.js


+ 7 - 2
dist/preview release/what's new.md

@@ -1,11 +1,15 @@
 # 3.2.0
 
 ## Major updates
+- Improved building process: We now run a full visual validation test for each pull request. Furthermore, code comments and what's new updates are now mandatory ([sebavan](https://github.com/sebavan))
 - Introduced texture binding atlas. This optimization allows the engine to reuse texture bindings instead of rebinding textures when they are not on constant sampler indexes ([deltakosh](https://github.com/deltakosh))
 - New [AnimationGroup class](http://doc.babylonjs.com/how_to/group) to control simultaneously multiple animations with different targets ([deltakosh](https://github.com/deltakosh))
+- `WebVRCamera` now supports GearVR ([brianzinn](https://github.com/brianzinn))
+- New glTF [serializer](https://github.com/BabylonJS/Babylon.js/tree/master/serializers/src/glTF/2.0). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))
 
 ## Updates
-
+- Tons of functions and classes received the code comments they deserved (All the community)
+- Added support for all RGBA orders (BGR, RGB, etc..) for the DDS loader ([deltakosh](https://github.com/deltakosh))
 - Improved [SceneOptimizer](http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer) to provide better adapatability ([deltakosh](https://github.com/deltakosh))
 - Improved `scene.isReady()` function which now takes in account shadows and LOD ([deltakosh](https://github.com/deltakosh))
 - New watcher configuration for VSCode. Now the task only compiles changed files ([sebavan](https://github.com/sebavan))
@@ -19,7 +23,8 @@
    ([carloslanderas](https://github.com/carloslanderas))
 - VRHelper now exposes onNewMeshPicked observable that will notify a PickingInfo object after meshSelectionPredicate evaluation
    ([carloslanderas](https://github.com/carloslanderas))
-- `AssetsManager` will now clear its `tasks` lsit from all successfully loaded tasks ([deltakosh](https://github.com/deltakosh))
+- `AssetsManager` will now clear its `tasks` list from all successfully loaded tasks ([deltakosh](https://github.com/deltakosh))
+- Added documentation to WebVRCamera and VRExperienceHelper ([trevordev](https://github.com/trevordev))
 - Introduced `isStroke` on `HighlightLayerOptions` which makes the highlight solid ([PixelsCommander](https://github.com/pixelscommander))
 
 ## Bug fixes

+ 11 - 0
gui/src/advancedDynamicTexture.ts

@@ -529,6 +529,17 @@ module BABYLON.GUI {
             return result;
         }
 
+        /**
+         * FullScreenUI is created in a layer. This allows it to be treated like any other layer.
+         * As such, if you have a multi camera setup, you can set the layerMask on the GUI as well.
+         * When the GUI is not Created as FullscreenUI it does not respect the layerMask.
+         * layerMask is set through advancedTexture.layer.layerMask
+		 * @param name name for the Texture
+		 * @param foreground render in foreground (default is true)
+		 * @param scene scene to be rendered in
+		 * @param sampling method for scaling to fit screen
+		 * @returns AdvancedDynamicTexture
+         */
         public static CreateFullscreenUI(name: string, foreground: boolean = true, scene: Nullable<Scene> = null, sampling = Texture.BILINEAR_SAMPLINGMODE): AdvancedDynamicTexture {
             var result = new AdvancedDynamicTexture(name, 0, 0, scene, false, sampling);
 

+ 65 - 3
gui/src/controls/textBlock.ts

@@ -16,11 +16,30 @@ module BABYLON.GUI {
         */
         public onTextChangedObservable = new Observable<TextBlock>();
 
-        get resizeToFit(): boolean {
+        /**
+        * An event triggered after the text was broken up into lines
+        * @type {BABYLON.Observable}
+        */
+        public onLinesReadyObservable = new Observable<TextBlock>();
+
+        /**
+         * Return the line list (you may need to use the onLinesReadyObservable to make sure the list is ready)
+         */
+        public get lines(): any[] {
+            return this._lines;
+        }
+        
+        /**
+         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+         */
+        public get resizeToFit(): boolean {
             return this._resizeToFit;
         }
 
-        set resizeToFit(value: boolean) {
+        /**
+         * Gets or sets an boolean indicating that the TextBlock will be resized to fit container
+         */        
+        public set resizeToFit(value: boolean) {
             this._resizeToFit = value;
 
             if (this._resizeToFit) {
@@ -29,10 +48,16 @@ module BABYLON.GUI {
             }
         }
 
+        /**
+         * Gets or sets a boolean indicating if text must be wrapped
+         */
         public get textWrapping(): boolean {
             return this._textWrapping;
         }
 
+        /**
+         * Gets or sets a boolean indicating if text must be wrapped
+         */        
         public set textWrapping(value: boolean) {
             if (this._textWrapping === value) {
                 return;
@@ -41,10 +66,16 @@ module BABYLON.GUI {
             this._markAsDirty();
         }
 
+        /**
+         * Gets or sets text to display
+         */
         public get text(): string {
             return this._text;
         }
 
+        /**
+         * Gets or sets text to display
+         */
         public set text(value: string) {
             if (this._text === value) {
                 return;
@@ -55,10 +86,16 @@ module BABYLON.GUI {
             this.onTextChangedObservable.notifyObservers(this);
         }
 
+        /**
+         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+         */
         public get textHorizontalAlignment(): number {
             return this._textHorizontalAlignment;
         }
 
+        /**
+         * Gets or sets text horizontal alignment (BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER by default)
+         */        
         public set textHorizontalAlignment(value: number) {
             if (this._textHorizontalAlignment === value) {
                 return;
@@ -68,10 +105,16 @@ module BABYLON.GUI {
             this._markAsDirty();
         }
 
+        /**
+         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+         */        
         public get textVerticalAlignment(): number {
             return this._textVerticalAlignment;
         }
 
+        /**
+         * Gets or sets text vertical alignment (BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER by default)
+         */           
         public set textVerticalAlignment(value: number) {
             if (this._textVerticalAlignment === value) {
                 return;
@@ -81,17 +124,33 @@ module BABYLON.GUI {
             this._markAsDirty();
         }
 
+        /**
+         * Gets or sets line spacing value
+         */
         public set lineSpacing(value: string | number) {
             if (this._lineSpacing.fromString(value)) {
                 this._markAsDirty();
             }
         }
 
+        /**
+         * Gets or sets line spacing value
+         */        
         public get lineSpacing(): string | number {
             return this._lineSpacing.toString(this._host);
         }
 
-        constructor(public name?: string, text: string = "") {
+        /**
+         * Creates a new TextBlock object
+         * @param name defines the name of the control
+         * @param text defines the text to display (emptry string by default)
+         */
+        constructor(
+            /**
+             * Defines the name of the control
+             */
+            public name?: string, 
+            text: string = "") {
             super(name);
 
             this.text = text;
@@ -126,6 +185,7 @@ module BABYLON.GUI {
             context.fillText(text, this._currentMeasure.left + x, y);
         }
 
+        /** @ignore */
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
 
@@ -151,6 +211,8 @@ module BABYLON.GUI {
                     this._lines.push(this._parseLine(_line, context));
                 }
             }
+
+            this.onLinesReadyObservable.notifyObservers(this);
         }
 
         protected _parseLine(line: string = '', context: CanvasRenderingContext2D): object {

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

@@ -40,7 +40,7 @@ module BABYLON.GLTF2 {
     }
 
     export class GLTFLoader implements IGLTFLoader {
-        public _gltf: IGLTF;
+        public _gltf: _IGLTF;
         public _babylonScene: Scene;
 
         private _disposed = false;
@@ -182,7 +182,7 @@ module BABYLON.GLTF2 {
         }
 
         private _loadData(data: IGLTFLoaderData): void {
-            this._gltf = <IGLTF>data.json;
+            this._gltf = <_IGLTF>data.json;
 
             // Assign the index of each object for convinience.
             GLTFLoader._AssignIndices(this._gltf.accessors);
@@ -1620,9 +1620,6 @@ module BABYLON.GLTF2 {
             }) as IGLTFLoaderFileRequest;
 
             this._requests.push(request);
-            request.onCompleteObservable.add(() => {
-                this._requests.splice(this._requests.indexOf(request), 1);
-            });
         }
 
         public _tryCatchOnError(handler: () => void): void {

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

@@ -284,7 +284,7 @@ module BABYLON.GLTF2 {
         texCoord?: number;
     }
 
-    export interface IGLTF extends IGLTFProperty {
+    export interface _IGLTF extends IGLTFProperty {
         accessors?: IGLTFAccessor[];
         animations?: IGLTFAnimation[];
         asset: IGLTFAsset;

+ 1 - 1
package.json

@@ -14,7 +14,7 @@
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
     },
-    "main": "dist/preview release/babylon.max.js",
+    "main": "dist/preview release/babylon.js",
     "files": [
         "package.json",
         "dist/preview release/babylon.d.ts",

+ 25 - 10
serializers/src/glTF/2.0/babylon.glTFData.ts

@@ -1,33 +1,42 @@
+/// <reference path="../../../../dist/babylon.glTFInterface.d.ts"/>
+
 module BABYLON {
     /**
      * Class for holding and downloading glTF file data
      */
     export class _GLTFData {
-        _glTFFiles: { [fileName: string]: string | Blob };
+        /**
+         * Object which contains the file name as the key and its data as the value.
+         */
+        glTFFiles: { [fileName: string]: string | Blob };
 
+        /**
+         * Initializes the glTF file object.
+         */
         public constructor() {
-            this._glTFFiles = {};
+            this.glTFFiles = {};
         }
+
         /**
-         * Downloads glTF data.
+         * Downloads the glTF data as files based on their names and data.
          */
         public downloadFiles(): void {
             /**
-            * Checks for a matching suffix at the end of a string (for ES5 and lower)
-            * @param str 
-            * @param suffix 
-            * 
-            * @returns {boolean} indicating whether the suffix matches or not
+            * Checks for a matching suffix at the end of a string (for ES5 and lower).
+            * @param str - Source string.
+            * @param suffix - Suffix to search for in the source string.
+            * @returns - Boolean indicating whether the suffix was found (true) or not (false).
             */
             function endsWith(str: string, suffix: string): boolean {
                 return str.indexOf(suffix, str.length - suffix.length) !== -1;
             }
-            for (let key in this._glTFFiles) {
+
+            for (let key in this.glTFFiles) {
                 let link = document.createElement('a');
                 document.body.appendChild(link);
                 link.setAttribute("type", "hidden");
                 link.download = key;
-                let blob = this._glTFFiles[key];
+                let blob = this.glTFFiles[key];
                 let mimeType;
 
                 if (endsWith(key, ".glb")) {
@@ -39,6 +48,12 @@ module BABYLON {
                 else if (endsWith(key, ".gltf")) {
                     mimeType = { type: "model/gltf+json" };
                 }
+                else if (endsWith(key, ".jpeg" || ".jpg")) {
+                    mimeType = {type: GLTF2.ImageMimeType.JPEG};
+                }
+                else if (endsWith(key, ".png")) {
+                    mimeType = {type: GLTF2.ImageMimeType.PNG};
+                }
 
                 link.href = window.URL.createObjectURL(new Blob([blob], mimeType));
                 link.click();

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 516 - 224
serializers/src/glTF/2.0/babylon.glTFExporter.ts


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

@@ -0,0 +1,198 @@
+/// <reference path="../../../../dist/babylon.glTFInterface.d.ts"/>
+
+module BABYLON.GLTF2 {
+    /**
+     * Represents the components used for representing a physically-based specular glossiness material
+     */
+    interface IBabylonPbrSpecularGlossiness {
+        /**
+         * The diffuse color of the model, whose color values should be 
+         * normalized from 0 to 1.  
+         */
+        diffuse: Color3;
+        /**
+         * Represents the transparency of the material, from a range of 0 to 1.
+         */
+        opacity: number;
+        /**
+         * Represents how specular the material is, from a range of 0 to 1.
+         */
+        specular: Color3;
+        /**
+         * Represents how glossy the material is, from a range of 0 to 1.
+         */
+        glossiness: number;
+    }
+
+    /**
+     * Represents the components used for representing a physically-based metallic roughness material.
+     */
+    interface _IBabylonPbrMetallicRoughness {
+        /**
+         * The albedo color of the material, whose color components should be normalized from 0 to 1.
+         */
+        baseColor: Color3;
+        /**
+         * Represents the transparency of the material, from a range of 0 (transparent) to 1 (opaque).
+         */
+        opacity: number;
+        /**
+         * Represents the "metalness" of a material, from a range of 0 (dielectric) to 1 (metal).
+         */
+        metallic: number;
+        /**
+         * Represents the "roughness" of a material, from a range of 0 (completely smooth) to 1 (completely rough).
+         */
+        roughness: number;
+    }
+
+    /**
+     * Utility methods for working with glTF material conversion properties.  This class should only be used internally.
+     */
+    export class _GLTFMaterial {
+        /**
+         * Represents the dielectric specular values for R, G and B.
+         */
+        private static readonly dielectricSpecular = new Color3(0.04, 0.04, 0.04);
+        /**
+         * Epsilon value, used as a small tolerance value for a numeric value.
+         */
+        private static readonly epsilon = 1e-6;
+
+        /**
+         * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material.
+         * @param babylonStandardMaterial 
+         * @returns - glTF Metallic Roughness Material representation
+         */
+        public static ConvertToGLTFPBRMetallicRoughness(babylonStandardMaterial: StandardMaterial): IMaterialPbrMetallicRoughness {
+            const babylonSpecularGlossiness: IBabylonPbrSpecularGlossiness = {
+                diffuse: babylonStandardMaterial.diffuseColor,
+                opacity: babylonStandardMaterial.alpha,
+                specular: babylonStandardMaterial.specularColor || Color3.Black(),
+                glossiness: babylonStandardMaterial.specularPower / 256
+            };
+            if (babylonStandardMaterial.specularTexture) {
+
+            }
+            const babylonMetallicRoughness = _GLTFMaterial._ConvertToMetallicRoughness(babylonSpecularGlossiness);
+
+            const glTFPbrMetallicRoughness: IMaterialPbrMetallicRoughness = {
+                baseColorFactor: [
+                    babylonMetallicRoughness.baseColor.r,
+                    babylonMetallicRoughness.baseColor.g,
+                    babylonMetallicRoughness.baseColor.b,
+                    babylonMetallicRoughness.opacity
+                ],
+                metallicFactor: babylonMetallicRoughness.metallic,
+                roughnessFactor: babylonMetallicRoughness.roughness
+            };
+
+            return glTFPbrMetallicRoughness;
+        }
+
+        /**
+         * Converts Specular Glossiness to Metallic Roughness.  This is based on the algorithm used in the Babylon glTF 3ds Max Exporter.
+         * {@link https://github.com/BabylonJS/Exporters/blob/master/3ds%20Max/Max2Babylon/Exporter/BabylonExporter.GLTFExporter.Material.cs}
+         * @param  babylonSpecularGlossiness - Babylon specular glossiness parameters
+         * @returns - Babylon metallic roughness values
+         */
+        private static _ConvertToMetallicRoughness(babylonSpecularGlossiness: IBabylonPbrSpecularGlossiness): _IBabylonPbrMetallicRoughness {
+            const diffuse = babylonSpecularGlossiness.diffuse;
+            const opacity = babylonSpecularGlossiness.opacity;
+            const specular = babylonSpecularGlossiness.specular;
+            const glossiness = babylonSpecularGlossiness.glossiness;
+            
+            const oneMinusSpecularStrength = 1 - Math.max(specular.r, Math.max(specular.g, specular.b));
+            const diffusePerceivedBrightness = _GLTFMaterial.PerceivedBrightness(diffuse);
+            const specularPerceivedBrightness = _GLTFMaterial.PerceivedBrightness(specular);
+            const metallic = _GLTFMaterial.SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
+            const diffuseScaleFactor = oneMinusSpecularStrength/(1 - this.dielectricSpecular.r) / Math.max(1 - metallic, this.epsilon);
+            const baseColorFromDiffuse = diffuse.scale(diffuseScaleFactor);
+            const baseColorFromSpecular = specular.subtract(this.dielectricSpecular.scale(1 - metallic)).scale(1/ Math.max(metallic, this.epsilon));
+            const lerpColor = Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
+            let baseColor = new Color3();
+            lerpColor.clampToRef(0, 1, baseColor);
+
+            const babylonMetallicRoughness: _IBabylonPbrMetallicRoughness = {
+                baseColor: baseColor,
+                opacity: opacity,
+                metallic: metallic,
+                roughness: 1.0 - glossiness
+            };
+
+            return babylonMetallicRoughness;
+        }
+
+        /**
+         * Returns the perceived brightness value based on the provided color
+         * @param color - color used in calculating the perceived brightness
+         * @returns - perceived brightness value
+         */
+        private static PerceivedBrightness(color: Color3): number {
+            return Math.sqrt(0.299 * color.r * color.r + 0.587 * color.g * color.g + 0.114 * color.b * color.b);
+        }
+
+        /**
+         * Computes the metallic factor
+         * @param diffuse - diffused value
+         * @param specular - specular value
+         * @param oneMinusSpecularStrength - one minus the specular strength
+         * @returns - metallic value
+         */
+        public static SolveMetallic(diffuse: number, specular: number, oneMinusSpecularStrength: number): number {
+            if (specular < this.dielectricSpecular.r) {
+                return 0;
+            }
+
+            const a = this.dielectricSpecular.r;
+            const b = diffuse * oneMinusSpecularStrength /(1.0 - this.dielectricSpecular.r) + specular - 2.0 * this.dielectricSpecular.r;
+            const c = this.dielectricSpecular.r - specular;
+            const D = b * b - 4.0 * a * c;
+            return BABYLON.Scalar.Clamp((-b + Math.sqrt(D))/(2.0 * a));
+        }
+        
+        /**
+         * Gets the glTF alpha mode from the Babylon Material
+         * @param babylonMaterial - Babylon Material
+         * @returns - The Babylon alpha mode value
+         */
+        public static GetAlphaMode(babylonMaterial: Material): MaterialAlphaMode {
+            if (babylonMaterial instanceof StandardMaterial) {
+                const babylonStandardMaterial = babylonMaterial as StandardMaterial;
+                if ((babylonStandardMaterial.alpha != 1.0) || 
+                    (babylonStandardMaterial.diffuseTexture != null && babylonStandardMaterial.diffuseTexture.hasAlpha) ||
+                    (babylonStandardMaterial.opacityTexture != null)) {
+                    return  MaterialAlphaMode.BLEND;
+                }
+                else {
+                    return MaterialAlphaMode.OPAQUE;
+                }
+            }
+            else if (babylonMaterial instanceof PBRMetallicRoughnessMaterial) {
+                const babylonPBRMetallicRoughness = babylonMaterial as PBRMetallicRoughnessMaterial;
+
+                switch(babylonPBRMetallicRoughness.transparencyMode) {
+                    case PBRMaterial.PBRMATERIAL_OPAQUE: {
+                        return MaterialAlphaMode.OPAQUE;
+                    }
+                    case PBRMaterial.PBRMATERIAL_ALPHABLEND: {
+                        return MaterialAlphaMode.BLEND;
+                    }
+                    case PBRMaterial.PBRMATERIAL_ALPHATEST: {
+                        return MaterialAlphaMode.MASK;
+                    }
+                    case PBRMaterial.PBRMATERIAL_ALPHATESTANDBLEND: {
+                        console.warn("GLTF Exporter | Alpha test and blend mode not supported in glTF.  Alpha blend used instead.");
+                        return MaterialAlphaMode.BLEND;
+                    }
+                    default: {
+                        throw new Error("Unsupported alpha mode " + babylonPBRMetallicRoughness.transparencyMode);
+                    }
+                }
+            }
+            else {
+                throw new Error("Unsupported Babylon material type");
+            }   
+        }
+    }
+}

+ 45 - 21
serializers/src/glTF/2.0/babylon.glTFSerializer.ts

@@ -1,34 +1,58 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
+    /**
+     * Holds a collection of exporter options and parameters
+     */
+    export interface IExporterOptions {
+        /**
+         * Function which indicates whether a babylon mesh should be exported or not.
+         * @param mesh - source Babylon mesh. It is used to check whether it should be 
+         * exported to glTF or not.
+         * @returns boolean, which indicates whether the mesh should be exported (true) or not (false)
+         */
+        shouldExportMesh?(mesh: AbstractMesh): boolean;
+    };
+
+    /**
+     * Class for generating glTF data from a Babylon scene.
+     */
     export class GLTF2Export {
         /**
-         * Exports the geometry of a Mesh array in .gltf file format.
-         * If glb is set to true, exports as .glb.
-         * @param meshes 
-         * @param materials 
-         * 
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .gltf, .glb and associates textures
+         * Exports the geometry of the scene to .gltf file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating the glTF file.
+         * @param options - Exporter options.
+         * @returns - Returns an object with a .gltf file and associates texture names
          * as keys and their data and paths as values.
          */
-        public static GLTF(scene: BABYLON.Scene, filename: string): _GLTFData {
-            let glTFPrefix = filename.replace(/\.[^/.]+$/, "");
-            let gltfGenerator = new _GLTF2Exporter(scene);
-
-            return gltfGenerator._generateGLTF(glTFPrefix);
+        public static GLTF(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData {
+            const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");
+            const gltfGenerator = new GLTF2._Exporter(scene, options);
+            if (scene.isReady) {
+                return gltfGenerator._generateGLTF(glTFPrefix);
+            }
+            else {
+                throw new Error("glTF Serializer: Scene is not ready!");
+            } 
         }
+
         /**
-         * 
-         * @param meshes 
-         * @param filename 
-         * 
-         * @returns {[fileName: string]: string | Blob} Returns an object with a .glb filename as key and data as value
+         * Exports the geometry of the scene to .glb file format.
+         * @param scene - Babylon scene with scene hierarchy information.
+         * @param filePrefix - File prefix to use when generating glb file.
+         * @param options - Exporter options.
+         * @returns - Returns an object with a .glb filename as key and data as value
          */
-        public static GLB(scene: BABYLON.Scene, filename: string): _GLTFData {
-            let glTFPrefix = filename.replace(/\.[^/.]+$/, "");        
-            let gltfGenerator = new _GLTF2Exporter(scene);
-
-            return gltfGenerator._generateGLB(glTFPrefix);
+        public static GLB(scene: Scene, filePrefix: string, options?: IExporterOptions): _GLTFData {
+            const glTFPrefix = filePrefix.replace(/\.[^/.]+$/, "");        
+            const gltfGenerator = new GLTF2._Exporter(scene, options);
+            if (scene.isReady) {
+                return gltfGenerator._generateGLB(glTFPrefix);
+            }
+            else {
+                throw new Error("glTF Serializer: Scene is not ready!");
+            }  
         }
     }
 }

+ 19 - 0
src/Actions/babylon.actionManager.ts

@@ -319,6 +319,25 @@
         }
 
         /**
+         * Unregisters an action to this action manager
+         * @param action The action to be unregistered
+         * @return whether the action has been unregistered
+         */
+        public unregisterAction(action: Action): Boolean {
+            var index = this.actions.indexOf(action);
+            if (index !== -1) {
+                this.actions.splice(index, 1);
+                ActionManager.Triggers[action.trigger] -= 1;
+                if (ActionManager.Triggers[action.trigger] === 0) {
+                    delete ActionManager.Triggers[action.trigger]
+                }
+                delete action._actionManager;
+                return true;
+            }
+            return false;
+        }
+
+        /**
          * Process a specific trigger
          * @param {number} trigger - the trigger to process
          * @param evt {BABYLON.ActionEvent} the event details to be processed

+ 5 - 1
src/Cameras/Inputs/babylon.freeCameraDeviceOrientationInput.ts

@@ -1,4 +1,8 @@
 module BABYLON {
+    /**
+     * Takes information about the orientation of the device as reported by the deviceorientation event to orient the camera.
+     * Screen rotation is taken into account.
+     */
     export class FreeCameraDeviceOrientationInput implements ICameraInput<FreeCamera> {
         private _camera: FreeCamera;
 
@@ -74,4 +78,4 @@ module BABYLON {
     }
 
     (<any>CameraInputTypes)["FreeCameraDeviceOrientationInput"] = FreeCameraDeviceOrientationInput;
-}
+}

+ 98 - 5
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -1,14 +1,36 @@
 module BABYLON {
+    /**
+     * Options to modify the vr teleportation behavior.
+     */
     export interface VRTeleportationOptions {
-        floorMeshName?: string; // If you'd like to provide a mesh acting as the floor
+        /**
+         * The name of the mesh which should be used as the teleportation floor. (default: null)
+         */
+        floorMeshName?: string;
+        /**
+         * A list of meshes to be used as the teleportation floor. (default: empty)
+         */
         floorMeshes?: Mesh[];
     }
 
+    /**
+     * Options to modify the vr experience helper's behavior.
+     */
     export interface VRExperienceHelperOptions extends WebVROptions {
-        createDeviceOrientationCamera?: boolean; // Create a DeviceOrientationCamera to be used as your out of vr camera.
-        createFallbackVRDeviceOrientationFreeCamera?: boolean; // Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found
+        /**
+         * Create a DeviceOrientationCamera to be used as your out of vr camera.
+         */
+        createDeviceOrientationCamera?: boolean;
+        /**
+         * Create a VRDeviceOrientationFreeCamera to be used for VR when no external HMD is found.
+         */
+        createFallbackVRDeviceOrientationFreeCamera?: boolean;
     }
 
+    /**
+     * Helps to quickly add VR support to an existing scene.
+     * See http://doc.babylonjs.com/how_to/webvr_helper
+     */
     export class VRExperienceHelper {
         private _scene: Scene;
         private _position: Vector3;
@@ -166,10 +188,16 @@ module BABYLON {
 
         private _dpadPressed = true;
 
+        /**
+         * The mesh used to display where the user is going to teleport.
+         */
         public get teleportationTarget(): Mesh {
             return this._teleportationTarget;
         }
 
+        /**
+         * Sets the mesh to be used to display where the user is going to teleport.
+         */
         public set teleportationTarget(value: Mesh) {
             if (value) {
                 value.name = "teleportationTarget";
@@ -178,10 +206,16 @@ module BABYLON {
             }
         }
 
+        /**
+         * If the ray of the gaze should be displayed.
+         */
         public get displayGaze(): boolean {
             return this._displayGaze;
         }
 
+        /**
+         * Sets if the ray of the gaze should be displayed.
+         */
         public set displayGaze(value: boolean) {
             this._displayGaze = value;
             if (!value) {
@@ -189,10 +223,16 @@ module BABYLON {
             }
         }
 
+        /**
+         * If the ray of the LaserPointer should be displayed.
+         */
         public get displayLaserPointer(): boolean {
             return this._displayLaserPointer;
         }
 
+        /**
+         * Sets if the ray of the LaserPointer should be displayed.
+         */
         public set displayLaserPointer(value: boolean) {
             this._displayLaserPointer = value;
             if (!value) {
@@ -213,11 +253,16 @@ module BABYLON {
             }
         }
 
+        /**
+         * The deviceOrientationCamera used as the camera when not in VR.
+         */
         public get deviceOrientationCamera(): Nullable<DeviceOrientationCamera> {
             return this._deviceOrientationCamera;
         }
 
-        // Based on the current WebVR support, returns the current VR camera used
+        /**
+         * Based on the current WebVR support, returns the current VR camera used.
+         */
         public get currentVRCamera(): Nullable<Camera> {
             if (this._webVRready) {
                 return this._webVRCamera;
@@ -227,15 +272,27 @@ module BABYLON {
             }
         }
 
+        /**
+         * The webVRCamera which is used when in VR.
+         */
         public get webVRCamera(): WebVRFreeCamera {
             return this._webVRCamera;
         }
 
+        /**
+         * The deviceOrientationCamera that is used as a fallback when vr device is not connected.
+         */
         public get vrDeviceOrientationCamera(): Nullable<VRDeviceOrientationFreeCamera> {
             return this._vrDeviceOrientationCamera;
         }
 
-        constructor(scene: Scene, public webVROptions: VRExperienceHelperOptions = {}) {
+        /**
+         * Instantiates a VRExperienceHelper.
+         * Helps to quickly add VR support to an existing scene.
+         * @param scene The scene the VRExperienceHelper belongs to.
+         * @param webVROptions Options to modify the vr experience helper's behavior.
+         */
+        constructor(scene: Scene, /** Options to modify the vr experience helper's behavior. */public webVROptions: VRExperienceHelperOptions = {}) {
             this._scene = scene;
             this._canvas = scene.getEngine().getRenderingCanvas();
 
@@ -581,10 +638,16 @@ module BABYLON {
             }
         }
 
+        /**
+         * The position of the vr experience helper.
+         */
         public get position(): Vector3 {
             return this._position;
         }
 
+        /**
+         * Sets the position of the vr experience helper.
+         */
         public set position(value: Vector3) {
             this._position = value;
 
@@ -593,6 +656,9 @@ module BABYLON {
             }
         }
 
+        /**
+         * Enables controllers and user interactions suck as selecting and object or clicking on an object.
+         */
         public enableInteractions() {
             if (!this._interactionsEnabled) {
                 this._interactionsRequested = true;
@@ -644,6 +710,10 @@ module BABYLON {
             return false;
         }
 
+        /**
+         * Adds a floor mesh to be used for teleportation.
+         * @param floorMesh the mesh to be used for teleportation.
+         */
         public addFloorMesh(floorMesh: Mesh): void {
             if (!this._floorMeshesCollection) {
                 return;
@@ -656,6 +726,10 @@ module BABYLON {
             this._floorMeshesCollection.push(floorMesh);
         }
 
+        /**
+         * Removes a floor mesh from being used for teleportation.
+         * @param floorMesh the mesh to be removed.
+         */
         public removeFloorMesh(floorMesh: Mesh): void {
             if (!this._floorMeshesCollection) {
                 return
@@ -667,6 +741,10 @@ module BABYLON {
             }
         }
 
+        /**
+         * Enables interactions and teleportation using the VR controllers and gaze.
+         * @param vrTeleportationOptions options to modify teleportation behavior.
+         */
         public enableTeleportation(vrTeleportationOptions: VRTeleportationOptions = {}) {
             if (!this._teleportationInitialized) {
                 this._teleportationRequested = true;
@@ -1463,6 +1541,10 @@ module BABYLON {
             }
         }
 
+        /**
+         * Sets the color of the laser ray from the vr controllers.
+         * @param color new color for the ray.
+         */
         public changeLaserColor(color: Color3) {
             if (this._leftLaserPointer && this._leftLaserPointer.material) {
                 (<StandardMaterial>this._leftLaserPointer.material).emissiveColor = color;
@@ -1472,12 +1554,19 @@ module BABYLON {
             }
         }
 
+        /**
+         * Sets the color of the ray from the vr headsets gaze.
+         * @param color new color for the ray.
+         */
         public changeGazeColor(color: Color3) {
             if (this._gazeTracker.material) {
                 (<StandardMaterial>this._gazeTracker.material).emissiveColor = color;
             }
         }
 
+        /**
+         * Exits VR and disposes of the vr experience helper
+         */
         public dispose() {
             if (this.isInVRMode) {
                 this.exitVR();
@@ -1535,6 +1624,10 @@ module BABYLON {
             this._scene.unregisterBeforeRender(this.beforeRender);
         }
 
+        /**
+         * Gets the name of the VRExperienceHelper class
+         * @returns "VRExperienceHelper"
+         */
         public getClassName(): string {
             return "VRExperienceHelper";
         }

+ 204 - 26
src/Cameras/VR/babylon.webVRCamera.ts

@@ -4,45 +4,135 @@ declare var VRFrameData: any;
 
 module BABYLON {
     /**
-     * This is a copy of VRPose.
+     * This is a copy of VRPose. See https://developer.mozilla.org/en-US/docs/Web/API/VRPose
      * IMPORTANT!! The data is right-hand data.
      * @export
      * @interface DevicePose
      */
     export interface DevicePose {
+        /**
+         * The position of the device, values in array are [x,y,z].
+         */
         readonly position?: Float32Array;
+        /**
+         * The linearVelocity of the device, values in array are [x,y,z].
+         */
         readonly linearVelocity?: Float32Array;
+        /**
+         * The linearAcceleration of the device, values in array are [x,y,z].
+         */
         readonly linearAcceleration?: Float32Array;
 
+        /**
+         * The orientation of the device in a quaternion array, values in array are [x,y,z,w].
+         */
         readonly orientation?: Float32Array;
+        /**
+         * The angularVelocity of the device, values in array are [x,y,z].
+         */
         readonly angularVelocity?: Float32Array;
+        /**
+         * The angularAcceleration of the device, values in array are [x,y,z].
+         */
         readonly angularAcceleration?: Float32Array;
     }
 
+     /**
+     * Interface representing a pose controlled object in Babylon.
+     * A pose controlled object has both regular pose values as well as pose values 
+     * from an external device such as a VR head mounted display
+     */
     export interface PoseControlled {
+        /**
+         * The position of the object in babylon space.
+         */
         position: Vector3;
+        /**
+         * The rotation quaternion of the object in babylon space.
+         */
         rotationQuaternion: Quaternion;
+        /**
+         * The position of the device in babylon space.
+         */
         devicePosition?: Vector3;
+        /**
+         * The rotation quaternion of the device in babylon space.
+         */
         deviceRotationQuaternion: Quaternion;
+        /**
+         * The raw pose coming from the device.
+         */
         rawPose: Nullable<DevicePose>;
+        /**
+         * The scale of the device to be used when translating from device space to babylon space.
+         */
         deviceScaleFactor: number;
+        /**
+         * Updates the poseControlled values based on the input device pose.
+         * @param poseData the pose data to update the object with
+         */
         updateFromDevice(poseData: DevicePose): void;
     }
 
+    /**
+     * Set of options to customize the webVRCamera
+     */
     export interface WebVROptions {
-        trackPosition?: boolean; //for the sake of your users - set it to true.
+        /**
+         * Sets if the webVR camera should be tracked to the vrDevice. (default: true)
+         */
+        trackPosition?: boolean;
+        /**
+         * Sets the scale of the vrDevice in babylon space. (default: 1)
+         */
         positionScale?: number;
-        displayName?: string; //if there are more than one VRDisplays.
-        controllerMeshes?: boolean; // should the native controller meshes be initialized
-        defaultLightingOnControllers?: boolean; // creating a default HemiLight only on controllers
-        useCustomVRButton?: boolean; // if you don't want to use the default VR button of the helper
-        customVRButton?: HTMLButtonElement; //if you'd like to provide your own button to the VRHelper
-        rayLength?: number; // to change the length of the ray for gaze/controllers.
-        defaultHeight?: number; // to change the default offset from the ground to account for user's height
+        /**
+         * If there are more than one VRDisplays, this will choose the display matching this name. (default: pick first vrDisplay)
+         */
+        displayName?: string;
+        /**
+         * Should the native controller meshes be initialized. (default: true)
+         */
+        controllerMeshes?: boolean;
+        /**
+         * Creating a default HemiLight only on controllers. (default: true)
+         */
+        defaultLightingOnControllers?: boolean;
+        /**
+         * If you don't want to use the default VR button of the helper. (default: false)
+         */
+        useCustomVRButton?: boolean;
+
+        /**
+         * If you'd like to provide your own button to the VRHelper. (default: standard babylon vr button)
+         */
+        customVRButton?: HTMLButtonElement;
+
+        /**
+         * To change the length of the ray for gaze/controllers. (default: 100)
+         */
+        rayLength?: number;
+
+        /**
+         * To change the default offset from the ground to account for user's height. (default: 1.7)
+         */
+        defaultHeight?: number;
+
     }
 
+    /**
+     * This represents a WebVR camera.
+     * The WebVR camera is Babylon's simple interface to interaction with Windows Mixed Reality, HTC Vive and Oculus Rift.
+     * @example http://doc.babylonjs.com/how_to/webvr_camera
+     */
     export class WebVRFreeCamera extends FreeCamera implements PoseControlled {
+        /**
+         * The vrDisplay tied to the camera. See https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay
+         */
         public _vrDevice: any = null;
+        /**
+         * The rawPose of the vrDevice.
+         */
         public rawPose: Nullable<DevicePose> = null;
         private _onVREnabled: (success: boolean) => void;
         private _specsVersion: string = "1.1";
@@ -58,24 +148,51 @@ module BABYLON {
 
         private _standingMatrix: Nullable<Matrix> = null;
 
-        // Represents device position and rotation in babylon space
+        /**
+         * Represents device position in babylon space.
+         */
         public devicePosition = Vector3.Zero();
+        /**
+         * Represents device rotation in babylon space.
+         */
         public deviceRotationQuaternion = Quaternion.Identity();
 
+        /**
+         * The scale of the device to be used when translating from device space to babylon space.
+         */
         public deviceScaleFactor: number = 1;
 
         private _deviceToWorld = Matrix.Identity();
         private _worldToDevice = Matrix.Identity();
 
+        /**
+         * References to the webVR controllers for the vrDevice.
+         */
         public controllers: Array<WebVRController> = [];
+        /**
+         * Emits an event when a controller is attached.
+         */
         public onControllersAttachedObservable = new Observable<Array<WebVRController>>();
+        /**
+         * Emits an event when a controller's mesh has been loaded;
+         */
         public onControllerMeshLoadedObservable = new Observable<WebVRController>();
-
-        public rigParenting: boolean = true; // should the rig cameras be used as parent instead of this camera.
+        /**
+         * If the rig cameras be used as parent instead of this camera.
+         */
+        public rigParenting: boolean = true;
 
         private _lightOnControllers: HemisphericLight;
 
-        private _defaultHeight = 0;
+        private _defaultHeight?: number = undefined;
+
+        /**
+         * Instantiates a WebVRFreeCamera.
+         * @param name The name of the WebVRFreeCamera
+         * @param position The starting anchor position for the camera
+         * @param scene The scene the camera belongs to
+         * @param webVROptions a set of customizable options for the webVRCamera
+         */
         constructor(name: string, position: Vector3, scene: Scene, private webVROptions: WebVROptions = {}) {
             super(name, position, scene);
             this._cache.position = Vector3.Zero();
@@ -164,18 +281,26 @@ module BABYLON {
             });
         }
 
-        public deviceDistanceToRoomGround = () => {
-            if (this._standingMatrix) {
+        /**
+         * Gets the device distance from the ground.
+         * @returns the distance from the vrDevice to ground in device space. If standing matrix is not supported for the vrDevice 0 is returned.
+         */
+        public deviceDistanceToRoomGround(): number {
+            if (this._standingMatrix && this._defaultHeight === undefined) {
                 // Add standing matrix offset to get real offset from ground in room
                 this._standingMatrix.getTranslationToRef(this._workingVector);
                 return this._deviceRoomPosition.y + this._workingVector.y
-            } else {
-                return this._defaultHeight;
             }
+            //If VRDisplay does not inform stage parameters and no default height is set we fallback to zero.
+            return this._defaultHeight || 0;            
         }
 
-        public useStandingMatrix = (callback = (bool: boolean) => { }) => {
-            // Use standing matrix if availible
+        /**
+         * Enables the standing matrix when supported. This can be used to position the user's view the correct height from the ground.
+         * @param callback will be called when the standing matrix is set. Callback parameter is if the standing matrix is supported.
+         */
+        public useStandingMatrix(callback = (bool: boolean) => { }) {
+            // Use standing matrix if available
             if (!navigator || !navigator.getVRDisplays) {
                 callback(false);
             } else {
@@ -192,17 +317,25 @@ module BABYLON {
                                 }
                             });
                         }
-                        callback(true)
+                        callback(true);
                     }
-                })
+                });
             }
         }
 
+        /**
+         * Disposes the camera
+         */
         public dispose(): void {
             this.getEngine().onVRRequestPresentComplete.removeCallback(this._onVREnabled);
             super.dispose();
         }
 
+        /**
+         * Gets a vrController by name.
+         * @param name The name of the controller to retreive
+         * @returns the controller matching the name specified or null if not found
+         */
         public getControllerByName(name: string): Nullable<WebVRController> {
             for (var gp of this.controllers) {
                 if (gp.hand === name) {
@@ -214,6 +347,9 @@ module BABYLON {
         }
 
         private _leftController: Nullable<WebVRController>;
+        /**
+         * The controller corrisponding to the users left hand.
+         */
         public get leftController(): Nullable<WebVRController> {
             if (!this._leftController) {
                 this._leftController = this.getControllerByName("left");
@@ -223,6 +359,9 @@ module BABYLON {
         };
 
         private _rightController: Nullable<WebVRController>;
+        /**
+         * The controller corrisponding to the users right hand.
+         */
         public get rightController(): Nullable<WebVRController> {
             if (!this._rightController) {
                 this._rightController = this.getControllerByName("right");
@@ -232,7 +371,11 @@ module BABYLON {
         };
 
 
-
+        /**
+         * Casts a ray forward from the vrCamera's gaze.
+         * @param length Length of the ray (default: 100)
+         * @returns the ray corrisponding to the gaze
+         */
         public getForwardRay(length = 100): Ray {
             if (this.leftCamera) {
                 // Use left eye to avoid computation to compute center on every call
@@ -243,6 +386,9 @@ module BABYLON {
             }
         }
 
+        /**
+         * Updates the camera based on device's frame data
+         */
         public _checkInputs(): void {
             if (this._vrDevice && this._vrDevice.isPresenting) {
                 this._vrDevice.getFrameData(this._frameData);
@@ -253,6 +399,10 @@ module BABYLON {
             super._checkInputs();
         }
 
+        /**
+         * Updates the poseControlled values based on the input device pose.
+         * @param poseData Pose coming from the device
+         */
         updateFromDevice(poseData: DevicePose) {
             if (poseData && poseData.orientation) {
                 this.rawPose = poseData;
@@ -277,10 +427,8 @@ module BABYLON {
          * within a user-interaction callback. Example:
          * <pre> scene.onPointerDown = function() { camera.attachControl(canvas); }</pre>
          * 
-         * @param {HTMLElement} element 
-         * @param {boolean} [noPreventDefault] 
-         * 
-         * @memberOf WebVRFreeCamera
+         * @param element html element to attach the vrDevice to
+         * @param noPreventDefault prevent the default html element operation when attaching the vrDevice
          */
         public attachControl(element: HTMLElement, noPreventDefault?: boolean): void {
             super.attachControl(element, noPreventDefault);
@@ -293,6 +441,11 @@ module BABYLON {
             }
         }
 
+        /**
+         * Detaches the camera from the html element and disables VR
+         * 
+         * @param element html element to detach from
+         */
         public detachControl(element: HTMLElement): void {
             this.getScene().gamepadManager.onGamepadConnectedObservable.remove(this._onGamepadConnectedObserver);
             this.getScene().gamepadManager.onGamepadDisconnectedObservable.remove(this._onGamepadDisconnectedObserver);
@@ -302,16 +455,26 @@ module BABYLON {
             this.getEngine().disableVR();
         }
 
+        /**
+         * @returns the name of this class
+         */
         public getClassName(): string {
             return "WebVRFreeCamera";
         }
 
+        /**
+         * Calls resetPose on the vrDisplay
+         * See: https://developer.mozilla.org/en-US/docs/Web/API/VRDisplay/resetPose
+         */
         public resetToCurrentRotation() {
             //uses the vrDisplay's "resetPose()".
             //pitch and roll won't be affected.
             this._vrDevice.resetPose();
         }
 
+        /**
+         * Updates the rig cameras (left and right eye)
+         */
         public _updateRigCameras() {
             var camLeft = <TargetCamera>this._rigCameras[0];
             var camRight = <TargetCamera>this._rigCameras[1];
@@ -328,6 +491,10 @@ module BABYLON {
 
         private updateCacheCalled: boolean;
 
+        /**
+         * Updates the cached values of the camera
+         * @param ignoreParentClass ignores updating the parent class's cache (default: false)
+         */
         public _updateCache(ignoreParentClass?: boolean): void {
             if (!this.rotationQuaternion.equals(this._cache.rotationQuaternion) || !this.position.equals(this._cache.position)) {
                 // Update to ensure devicePosition is up to date with most recent _deviceRoomPosition
@@ -367,6 +534,9 @@ module BABYLON {
             this.updateCacheCalled = false;
         }
 
+        /**
+         * Updates the current device position and rotation in the babylon world
+         */
         public update() {
             // Get current device position in babylon world
             Vector3.TransformCoordinatesToRef(this._deviceRoomPosition, this._deviceToWorld, this.devicePosition);
@@ -378,6 +548,11 @@ module BABYLON {
 
             super.update();
         }
+
+        /**
+         * Gets the view matrix of this camera (Always set to identity as left and right eye cameras contain the actual view matrix)
+         * @returns an identity matrix
+         */
         public _getViewMatrix(): Matrix {
             return Matrix.Identity();
         }
@@ -447,6 +622,9 @@ module BABYLON {
         private _onGamepadConnectedObserver: Nullable<Observer<Gamepad>>;
         private _onGamepadDisconnectedObserver: Nullable<Observer<Gamepad>>;
 
+        /**
+         * Initializes the controllers and their meshes
+         */
         public initControllers() {
             this.controllers = [];
 

+ 11 - 9
src/Cameras/babylon.camera.ts

@@ -34,7 +34,7 @@
             return Camera._FOVMODE_VERTICAL_FIXED;
         }
 
-		/**
+        /**
          * This setting aligns the left and right bounds of the viewport to the left and right bounds of the camera frustum.
          *
          */
@@ -78,6 +78,10 @@
         @serializeAsVector3()
         public position: Vector3;
 
+        /**
+         * The vector the camera should consider as up.
+         * (default is Vector3(0, 1, 0) aka Vector3.Up())
+         */
         @serializeAsVector3()
         public upVector = Vector3.Up();
 
@@ -94,8 +98,7 @@
         public orthoTop: Nullable<number> = null;
 
         /**
-         * default : 0.8
-         * FOV is set in Radians.
+         * FOV is set in Radians. (default is 0.8)
          */
         @serialize()
         public fov = 0.8;
@@ -116,16 +119,15 @@
         public viewport = new Viewport(0, 0, 1.0, 1.0);
 
         /**
-        * Restricts the camera to viewing objects with the same layerMask.
-        * A camera with a layerMask of 1 will render meshes with no layerMask and meshes with a layerMask of 1.
-        */
+         * Restricts the camera to viewing objects with the same layerMask.
+         * A camera with a layerMask of 1 will render mesh.layerMask & camera.layerMask!== 0
+         */
         @serialize()
         public layerMask: number = 0x0FFFFFFF;
 
         /**
-        * default : FOVMODE_VERTICAL_FIXED
-        * fovMode sets the camera frustum bounds to the viewport bounds.
-        */
+         * fovMode sets the camera frustum bounds to the viewport bounds. (default is FOVMODE_VERTICAL_FIXED)
+         */
         @serialize()
         public fovMode: number = Camera.FOVMODE_VERTICAL_FIXED;
 

+ 14 - 1
src/Cameras/babylon.cameraInputsManager.ts

@@ -28,6 +28,12 @@ module BABYLON {
             this.checkInputs = () => { };
         }
 
+        /**
+         * Add an input method to a camera.
+         * builtin inputs example: camera.inputs.addGamepad();
+         * custom inputs example: camera.inputs.add(new BABYLON.FreeCameraGamepadInput());
+         * @param input camera input method
+         */
         public add(input: ICameraInput<TCamera>) {
             var type = input.getSimpleName();
             if (this.attached[type]) {
@@ -49,7 +55,11 @@ module BABYLON {
                 input.attachControl(this.attachedElement);
             }
         }
-
+        /**
+         * Remove a specific input method from a camera
+         * example: camera.inputs.remove(camera.inputs.attached.mouse);
+         * @param inputToRemove camera input method
+         */
         public remove(inputToRemove: ICameraInput<TCamera>) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
@@ -129,6 +139,9 @@ module BABYLON {
             }
         }
 
+        /**
+         * Remove all attached input methods from a camera
+         */
         public clear() {
             if (this.attachedElement) {
                 this.detachElement(this.attachedElement, true);

+ 25 - 2
src/Cameras/babylon.deviceOrientationCamera.ts

@@ -1,20 +1,38 @@
 module BABYLON {
     // We're mainly based on the logic defined into the FreeCamera code
+    /**
+     * This is a camera specifically designed to react to device orientation events such as a modern mobile device
+     * being tilted forward or back and left or right.
+     */
     export class DeviceOrientationCamera extends FreeCamera {
 
         private _initialQuaternion: Quaternion;
         private _quaternionCache: Quaternion;
 
+        /**
+         * Creates a new device orientation camera. @see DeviceOrientationCamera
+         * @param name The name of the camera
+         * @param position The start position camera
+         * @param scene The scene the camera belongs to
+         */
         constructor(name: string, position: Vector3, scene: Scene) {
             super(name, position, scene);
             this._quaternionCache = new Quaternion();
             this.inputs.addDeviceOrientation();
         }
 
+        /**
+         * Gets the current instance class name ("DeviceOrientationCamera").
+         * This helps avoiding instanceof at run time.
+         * @returns the class name
+         */
         public getClassName(): string {
             return "DeviceOrientationCamera";
         }
 
+        /**
+         * Checks and applies the current values of the inputs to the camera. (Internal use only)
+         */
         public _checkInputs(): void {
             super._checkInputs();
             this._quaternionCache.copyFrom(this.rotationQuaternion);
@@ -23,7 +41,12 @@ module BABYLON {
             }
         }
 
-        public resetToCurrentRotation(axis: Axis = Axis.Y) {
+        /**
+         * Reset the camera to its default orientation on the specified axis only.
+         * @param axis The axis to reset
+         */
+        public resetToCurrentRotation(axis: Axis = Axis.Y): void {
+
             //can only work if this camera has a rotation quaternion already.
             if (!this.rotationQuaternion) return;
 
@@ -45,4 +68,4 @@ module BABYLON {
             this._initialQuaternion.multiplyToRef(this.rotationQuaternion, this.rotationQuaternion);
         }
     }
-}
+}

+ 9 - 1
src/Cameras/babylon.freeCamera.ts

@@ -15,6 +15,10 @@
         public inputs: FreeCameraInputsManager;
 
         //-- begin properties for backward compatibility for inputs
+        /**
+         * Gets the input sensibility for a mouse input. (default is 2000.0)
+         * Higher values reduce sensitivity.
+         */
         public get angularSensibility(): number {
             var mouse = <FreeCameraMouseInput>this.inputs.attached["mouse"];
             if (mouse)
@@ -23,6 +27,10 @@
             return 0;
         }
 
+        /**
+         * Sets the input sensibility for a mouse input. (default is 2000.0)
+         * Higher values reduce sensitivity.
+         */
         public set angularSensibility(value: number) {
             var mouse = <FreeCameraMouseInput>this.inputs.attached["mouse"];
             if (mouse)
@@ -212,4 +220,4 @@
             return "FreeCamera";
         }
     }
-} 
+}

+ 15 - 1
src/Collisions/babylon.collisionCoordinator.ts

@@ -44,12 +44,26 @@ module BABYLON {
         boxMaximum: Array<number>;
     }
 
+    /**
+     * Interface describing the value associated with a geometry
+     */
     export interface SerializedGeometry {
+        /**
+         * Defines the unique ID of the geometry
+         */
         id: string;
+        /**
+         * Defines the array containing the positions
+         */
         positions: Float32Array;
+        /**
+         * Defines the array containing the indices
+         */        
         indices: Uint32Array;
+        /**
+         * Defines the array containing the normals
+         */        
         normals: Float32Array;
-        //uvs?: Float32Array;
     }
 
     export interface BabylonMessage {

+ 37 - 18
src/Engine/babylon.engine.ts

@@ -539,7 +539,7 @@
         }
 
         public static get Version(): string {
-            return "3.2.0-alpha4";
+            return "3.2.0-alpha5";
         }
 
         // Updatable statics so stick with vars here
@@ -733,7 +733,6 @@
         protected _activeChannel = 0;
         private _currentTextureChannel = -1;
         protected _boundTexturesCache: { [key: string]: Nullable<InternalTexture> } = {};
-        protected _boundTexturesStack = new Array<InternalTexture>();
         protected _currentEffect: Nullable<Effect>;
         protected _currentProgram: Nullable<WebGLProgram>;
         private _compiledEffects: { [key: string]: Effect } = {}
@@ -751,6 +750,8 @@
         private _currentInstanceLocations = new Array<number>();
         private _currentInstanceBuffers = new Array<WebGLBuffer>();
         private _textureUnits: Int32Array;
+        private _firstBoundInternalTextureTracker = new DummyInternalTextureTracker();
+        private _lastBoundInternalTextureTracker = new DummyInternalTextureTracker();
 
         private _workingCanvas: Nullable<HTMLCanvasElement>;
         private _workingContext: Nullable<CanvasRenderingContext2D>;
@@ -824,6 +825,10 @@
          * @param adaptToDeviceRatio defines whether to adapt to the device's viewport characteristics (default: false)
          */
         constructor(canvasOrContext: Nullable<HTMLCanvasElement | WebGLRenderingContext>, antialias?: boolean, options?: EngineOptions, adaptToDeviceRatio: boolean = false) {
+
+            // Register promises
+            PromisePolyfill.Apply();
+
             let canvas: Nullable<HTMLCanvasElement> = null;
             Engine.Instances.push(this);
 
@@ -1091,6 +1096,8 @@
                 this._currentBufferPointers[i] = new BufferPointer();
             }
 
+            this._linkTrackers(this._firstBoundInternalTextureTracker, this._lastBoundInternalTextureTracker);
+
             // Load WebVR Devices
             if (options.autoEnableWebVR) {
                 this.initWebVR();
@@ -4740,14 +4747,19 @@
         }
 
         private _moveBoundTextureOnTop(internalTexture: InternalTexture): void {
-            let index = this._boundTexturesStack.indexOf(internalTexture);
-
-            if (index > -1 && index !== this._boundTexturesStack.length - 1) {
-                this._boundTexturesStack.splice(index, 1);
-                this._boundTexturesStack.push(internalTexture);
+            if (this.disableTextureBindingOptimization || this._lastBoundInternalTextureTracker.previous === internalTexture) {
+                return;
             }
-        }
 
+            // Remove
+            this._linkTrackers(internalTexture.previous, internalTexture.next);
+
+            // Bind last to it
+            this._linkTrackers(this._lastBoundInternalTextureTracker.previous, internalTexture);
+
+            // Bind to dummy
+            this._linkTrackers(internalTexture, this._lastBoundInternalTextureTracker);
+        }
 
         private _getCorrectTextureChannel(channel: number, internalTexture: Nullable<InternalTexture>): number {
             if (!internalTexture) {
@@ -4772,7 +4784,7 @@
 
                         // We need to recycle the oldest bound texture, sorry.
                         this._textureCollisions.addCount(1, false);
-                        return this._removeDesignatedSlot(this._boundTexturesStack[0]);
+                        return this._removeDesignatedSlot(<InternalTexture>this._firstBoundInternalTextureTracker.next);
                     }
                 }
             }
@@ -4780,20 +4792,25 @@
             return channel;
         }
 
+        private _linkTrackers(previous: Nullable<IInternalTextureTracker>, next: Nullable<IInternalTextureTracker>) {
+            previous!.next = next;
+            next!.previous = previous;
+        }
 
         private _removeDesignatedSlot(internalTexture: InternalTexture): number {
             let currentSlot = internalTexture._designatedSlot;
+            if (currentSlot === -1) {
+                return -1;
+            }
 
             internalTexture._designatedSlot = -1;
-            let index = this._boundTexturesStack.indexOf(internalTexture);
 
-            if (index > -1) {
-                this._boundTexturesStack.splice(index, 1);
-                if (currentSlot > -1) {
-                    this._boundTexturesCache[currentSlot] = null;
-                    this._nextFreeTextureSlots.push(currentSlot);
-                }
-            }
+            // Remove from bound list
+            this._linkTrackers(internalTexture.previous, internalTexture.next);
+
+            // Free the slot
+            this._boundTexturesCache[currentSlot] = null;
+            this._nextFreeTextureSlots.push(currentSlot);
 
             return currentSlot;
         }
@@ -4829,7 +4846,9 @@
                         if (slotIndex > -1) {
                             this._nextFreeTextureSlots.splice(slotIndex, 1);
                         }
-                        this._boundTexturesStack.push(texture);
+
+                        this._linkTrackers(this._lastBoundInternalTextureTracker.previous, texture);
+                        this._linkTrackers(texture, this._lastBoundInternalTextureTracker);
                     }
 
                     texture._designatedSlot = this._activeChannel;

+ 156 - 2
src/Materials/Textures/babylon.internalTexture.ts

@@ -1,80 +1,219 @@
 module BABYLON {
-    export class InternalTexture {
-
+    /**
+     * Class used to store data associated with WebGL texture data for the engine
+     * This class should not be used directly
+     */
+    export class InternalTexture implements IInternalTextureTracker {
+
+        /**
+         * The source of the texture data is unknown
+         */
         public static DATASOURCE_UNKNOWN = 0;
+        /**
+         * Texture data comes from an URL
+         */
         public static DATASOURCE_URL = 1;
+        /**
+         * Texture data is only used for temporary storage
+         */
         public static DATASOURCE_TEMP = 2;
+        /**
+         * Texture data comes from raw data (ArrayBuffer)
+         */
         public static DATASOURCE_RAW = 3;
+        /**
+         * Texture content is dynamic (video or dynamic texture)
+         */
         public static DATASOURCE_DYNAMIC = 4;
+        /**
+         * Texture content is generated by rendering to it
+         */
         public static DATASOURCE_RENDERTARGET = 5;
+        /**
+         * Texture content is part of a multi render target process
+         */
         public static DATASOURCE_MULTIRENDERTARGET = 6;
+        /**
+         * Texture data comes from a cube data file
+         */
         public static DATASOURCE_CUBE = 7;
+        /**
+         * Texture data comes from a raw cube data
+         */
         public static DATASOURCE_CUBERAW = 8;
+        /**
+         * Texture data come from a prefiltered cube data file
+         */
         public static DATASOURCE_CUBEPREFILTERED = 9;
+        /**
+         * Texture content is raw 3D data
+         */
         public static DATASOURCE_RAW3D = 10;
 
+        /**
+         * Defines if the texture is ready
+         */
         public isReady: boolean;
+        /**
+         * Defines if the texture is a cube texture
+         */
         public isCube: boolean;
+        /**
+         * Defines if the texture contains 3D data
+         */
         public is3D: boolean;
+        /**
+         * Gets the URL used to load this texture
+         */
         public url: string;
+        /**
+         * Gets the sampling mode of the texture
+         */
         public samplingMode: number;
+        /**
+         * Gets a boolean indicating if the texture needs mipmaps generation
+         */
         public generateMipMaps: boolean;
+        /**
+         * Gets the number of samples used by the texture (WebGL2+ only)
+         */
         public samples: number;
+        /**
+         * Gets the type of the texture
+         */
         public type: number;
+        /**
+         * Gets the format of the texture 
+         */
         public format: number;
+        /**
+         * Observable called when the texture is loaded
+         */
         public onLoadedObservable = new Observable<InternalTexture>();
+        /**
+         * Gets the width of the texture
+         */
         public width: number;
+        /**
+         * Gets the height of the texture
+         */
         public height: number;
+        /**
+         * Gets the depth of the texture
+         */
         public depth: number;
+        /**
+         * Gets the initial width of the texture (It could be rescaled if the current system does not support non power of two textures)
+         */
         public baseWidth: number;
+        /**
+         * Gets the initial height of the texture (It could be rescaled if the current system does not support non power of two textures)
+         */
         public baseHeight: number;
+        /**
+         * Gets the initial depth of the texture (It could be rescaled if the current system does not support non power of two textures)
+         */
         public baseDepth: number;
+        /**
+         * Gets a boolean indicating if the texture is inverted on Y axis
+         */
         public invertY: boolean;
 
+        /**
+         * Gets or set the previous tracker in the list
+         */
+        public previous: Nullable<IInternalTextureTracker> = null
+        /**
+         * Gets or set the next tracker in the list
+         */
+        public next: Nullable<IInternalTextureTracker> = null
+
         // Private
+        /** @ignore */
         public _initialSlot = -1;
+        /** @ignore */
         public _designatedSlot = -1;
+        /** @ignore */
         public _dataSource = InternalTexture.DATASOURCE_UNKNOWN;
+        /** @ignore */
         public _buffer: Nullable<ArrayBuffer | HTMLImageElement>;
+        /** @ignore */
         public _bufferView: Nullable<ArrayBufferView>;
+        /** @ignore */
         public _bufferViewArray: Nullable<ArrayBufferView[]>;
+        /** @ignore */
         public _size: number;
+        /** @ignore */
         public _extension: string;
+        /** @ignore */
         public _files: Nullable<string[]>;
+        /** @ignore */
         public _workingCanvas: HTMLCanvasElement;
+        /** @ignore */
         public _workingContext: CanvasRenderingContext2D;
+        /** @ignore */
         public _framebuffer: Nullable<WebGLFramebuffer>;
+        /** @ignore */
         public _depthStencilBuffer: Nullable<WebGLRenderbuffer>;
+        /** @ignore */
         public _MSAAFramebuffer: Nullable<WebGLFramebuffer>;
+        /** @ignore */
         public _MSAARenderBuffer: Nullable<WebGLRenderbuffer>;
+        /** @ignore */
         public _attachments: Nullable<number[]>;
+        /** @ignore */
         public _cachedCoordinatesMode: Nullable<number>;
+        /** @ignore */
         public _cachedWrapU: Nullable<number>;
+        /** @ignore */
         public _cachedWrapV: Nullable<number>;
+        /** @ignore */
         public _cachedWrapR: Nullable<number>;
+        /** @ignore */
         public _cachedAnisotropicFilteringLevel: Nullable<number>;
+        /** @ignore */
         public _isDisabled: boolean;
+        /** @ignore */
         public _compression: Nullable<string>;
+        /** @ignore */
         public _generateStencilBuffer: boolean;
+        /** @ignore */
         public _generateDepthBuffer: boolean;
+        /** @ignore */
         public _sphericalPolynomial: Nullable<SphericalPolynomial>;
+        /** @ignore */
         public _lodGenerationScale: number;
+        /** @ignore */
         public _lodGenerationOffset: number;
+
         // The following three fields helps sharing generated fixed LODs for texture filtering
         // In environment not supporting the textureLOD extension like EDGE. They are for internal use only.
         // They are at the level of the gl texture to benefit from the cache.
+        /** @ignore */
         public _lodTextureHigh: BaseTexture;
+        /** @ignore */
         public _lodTextureMid: BaseTexture;
+        /** @ignore */
         public _lodTextureLow: BaseTexture;
 
+        /** @ignore */
         public _webGLTexture: Nullable<WebGLTexture>;
+        /** @ignore */
         public _references: number = 1;
         private _engine: Engine;
 
+        /**
+         * Gets the data source type of the texture (can be one of the BABYLON.InternalTexture.DATASOURCE_XXXX)
+         */
         public get dataSource(): number {
             return this._dataSource;
         }
 
+        /**
+         * Creates a new InternalTexture
+         * @param engine defines the engine to use
+         * @param dataSource defines the type of data that will be used
+         */
         constructor(engine: Engine, dataSource: number) {
             this._engine = engine;
             this._dataSource = dataSource;
@@ -82,10 +221,19 @@ module BABYLON {
             this._webGLTexture = engine._createTexture();
         }
 
+        /**
+         * Increments the number of references (ie. the number of {BABYLON.Texture} that point to it)
+         */
         public incrementReferences(): void {
             this._references++;
         }
 
+        /**
+         * Change the size of the texture (not the size of the content)
+         * @param width defines the new width
+         * @param height defines the new height
+         * @param depth defines the new depth (1 by default)
+         */
         public updateSize(width: int, height: int, depth: int = 1): void {
             this.width = width;
             this.height = height;
@@ -98,6 +246,7 @@ module BABYLON {
             this._size = width * height * depth;
         }
 
+        /** @ignore */
         public _rebuild(): void {
             var proxy: InternalTexture;
             this.isReady = false;
@@ -228,6 +377,9 @@ module BABYLON {
             }
         }
 
+        /**
+         * Dispose the current allocated resources
+         */
         public dispose(): void {
             if (!this._webGLTexture) {
                 return;
@@ -237,6 +389,8 @@ module BABYLON {
             if (this._references === 0) {
                 this._engine._releaseTexture(this);
                 this._webGLTexture = null;
+                this.previous = null;
+                this.next = null;
             }
         }
     }

+ 29 - 0
src/Materials/Textures/babylon.internalTextureTracker.ts

@@ -0,0 +1,29 @@
+module BABYLON {
+    /**
+     * Internal interface used to track {BABYLON.InternalTexture} already bound to the GL context
+     */
+    export interface IInternalTextureTracker {
+        /**
+         * Gets or set the previous tracker in the list
+         */
+        previous: Nullable<IInternalTextureTracker>;
+        /**
+         * Gets or set the next tracker in the list
+         */
+        next: Nullable<IInternalTextureTracker>;
+    }
+
+    /**
+     * Internal class used by the engine to get list of {BABYLON.InternalTexture} already bound to the GL context
+     */
+    export class DummyInternalTextureTracker {
+        /**
+         * Gets or set the previous tracker in the list
+         */
+        public previous: Nullable<IInternalTextureTracker> = null;
+        /**
+         * Gets or set the next tracker in the list
+         */
+        public next: Nullable<IInternalTextureTracker> = null;
+    }
+}

+ 212 - 93
src/Materials/Textures/babylon.videoTexture.ts

@@ -1,44 +1,127 @@
 module BABYLON {
+    /**
+     * Settings for finer control over video usage
+     */
+    export interface VideoTextureSettings {
+        /**
+         * Applies `autoplay` to video, if specified
+         */
+        autoPlay?: boolean;
+
+        /**
+         * Applies `loop` to video, if specified
+         */
+        loop?: boolean;
+
+        /**
+         * Automatically updates internal texture from video at every frame in the render loop
+         */
+        autoUpdateTexture: boolean;
+    }
+
     export class VideoTexture extends Texture {
-        public video: HTMLVideoElement;
+        /**
+         * Tells whether textures will be updated automatically or user is required to call `updateTexture` manually
+         */
+        public readonly autoUpdateTexture: boolean;
 
-        private _autoLaunch = true;
-        private _lastUpdate: number;
-        private _generateMipMaps: boolean
-        private _setTextureReady: () => void;
+        /**
+         * The video instance used by the texture internally
+         */
+        public readonly video: HTMLVideoElement;
+
+        private _generateMipMaps: boolean;
         private _engine: Engine;
 
         /**
          * Creates a video texture.
-         * Sample : https://doc.babylonjs.com/tutorials/01._Advanced_Texturing
-         * @param {Array} urlsOrVideo can be used to provide an array of urls or an already setup HTML video element.
+         * Sample : https://doc.babylonjs.com/how_to/video_texture
+         * @param {string | null} name optional name, will detect from video source, if not defined
+         * @param {(string | string[] | HTMLVideoElement)} src can be used to provide an url, array of urls or an already setup HTML video element.
          * @param {BABYLON.Scene} scene is obviously the current scene.
          * @param {boolean} generateMipMaps can be used to turn on mipmaps (Can be expensive for videoTextures because they are often updated).
          * @param {boolean} invertY is false by default but can be used to invert video on Y axis
          * @param {number} samplingMode controls the sampling method and is set to TRILINEAR_SAMPLINGMODE by default
+         * @param {VideoTextureSettings} [settings] allows finer control over video usage
          */
-        constructor(name: string, urlsOrVideo: string[] | HTMLVideoElement, scene: Scene, generateMipMaps = false, invertY = false, samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE) {
+        constructor(
+            name: Nullable<string>,
+            src: string | string[] | HTMLVideoElement,
+            scene: Nullable<Scene>,
+            generateMipMaps = false,
+            invertY = false,
+            samplingMode: number = Texture.TRILINEAR_SAMPLINGMODE,
+            settings: VideoTextureSettings = {
+                autoPlay: true,
+                loop: true,
+                autoUpdateTexture: true,
+            }
+        ) {
             super(null, scene, !generateMipMaps, invertY);
 
-            var urls: Nullable<string[]> = null;
-            this.name = name;
+            this._engine = this.getScene()!.getEngine();
+            this._generateMipMaps = generateMipMaps;
+            this._samplingMode = samplingMode;
+            this.autoUpdateTexture = settings.autoUpdateTexture;
 
-            if (urlsOrVideo instanceof HTMLVideoElement) {
-                this.video = <any>urlsOrVideo;
-            } else {
-                urls = urlsOrVideo;
+            this.name = name || this._getName(src);
+            this.video = this._getVideo(src);
 
-                this.video = document.createElement("video");
-                this.video.autoplay = false;
-                this.video.loop = true;
-                Tools.SetCorsBehavior(urls, this.video);
+            if (settings.autoPlay !== undefined) {
+                this.video.autoplay = settings.autoPlay;
+            }
+            if (settings.loop !== undefined) {
+                this.video.loop = settings.loop;
             }
 
-            this._engine = (<Scene>this.getScene()).getEngine();
-            this._generateMipMaps = generateMipMaps;
-            this._samplingMode = samplingMode;
+            this.video.addEventListener("canplay", this._createInternalTexture);
+            this.video.addEventListener("paused", this._updateInternalTexture);
+            this.video.addEventListener("seeked", this._updateInternalTexture);
+            this.video.addEventListener("emptied", this.reset);
+
+            if (this.video.readyState >= this.video.HAVE_CURRENT_DATA) {
+                this._createInternalTexture();
+            }
+        }
+
+        private _getName(src: string | string[] | HTMLVideoElement): string {
+            if (src instanceof HTMLVideoElement) {
+                return src.currentSrc;
+            }
+    
+            if (typeof src === "object") {
+                return src.toString();
+            }
+    
+            return src;
+        };
+    
+        private _getVideo(src: string | string[] | HTMLVideoElement): HTMLVideoElement {
+            if (src instanceof HTMLVideoElement) {
+                return src;
+            }
+            const video: HTMLVideoElement = document.createElement("video");
+            if (typeof src === "string") {
+                video.src = src;
+            } else {
+                src.forEach(url => {
+                    const source = document.createElement("source");
+                    source.src = url;
+                    video.appendChild(source);
+                });
+            }
+            return video;
+        };
+
+        private _createInternalTexture = (): void => {
+            if (this._texture != null) {
+                return;
+            }
 
-            if (!this._engine.needPOTTextures || (Tools.IsExponentOfTwo(this.video.videoWidth) && Tools.IsExponentOfTwo(this.video.videoHeight))) {
+            if (
+                !this._engine.needPOTTextures ||
+                (Tools.IsExponentOfTwo(this.video.videoWidth) && Tools.IsExponentOfTwo(this.video.videoHeight))
+            ) {
                 this.wrapU = Texture.WRAP_ADDRESSMODE;
                 this.wrapV = Texture.WRAP_ADDRESSMODE;
             } else {
@@ -47,110 +130,146 @@
                 this._generateMipMaps = false;
             }
 
-            if (urls) {
-                this.video.addEventListener("canplay", () => {
-                    if (this._texture === undefined){ 
-                      this._createTexture();
-                    }
-                });
-                urls.forEach(url => {
-                    var source = document.createElement("source");
-                    source.src = url;
-                    this.video.appendChild(source);
-                });
-            } else {
-                this._createTexture();
-            }
-
-            this._lastUpdate = Tools.Now;
-        }
+            this._texture = this._engine.createDynamicTexture(
+                this.video.videoWidth,
+                this.video.videoHeight,
+                this._generateMipMaps,
+                this._samplingMode
+            );
+            this._texture.width;
 
-        private __setTextureReady(): void {
-            if (this._texture) {
-                this._texture.isReady = true;
-            }
-        }
+            this._updateInternalTexture();
 
-        private _createTexture(): void {
-            this._texture = this._engine.createDynamicTexture(this.video.videoWidth, this.video.videoHeight, this._generateMipMaps, this._samplingMode);
+            this._texture.isReady = true;
+        };
 
-            if (this._autoLaunch) {
-                this._autoLaunch = false;
-                this.video.play();
+        private reset = (): void => {
+            if (this._texture == null) {
+                return;
             }
-            this._setTextureReady = this.__setTextureReady.bind(this);
-            this.video.addEventListener("playing", this._setTextureReady);
-        }
-
+            this._texture.dispose();
+            this._texture = null;
+        };
 
+        /**
+         * Internal method to initiate `update`.
+         */
         public _rebuild(): void {
             this.update();
         }
 
-        public update(): boolean {
-            var now = Tools.Now;
+        /**
+         * Update Texture in the `auto` mode. Does not do anything if `settings.autoUpdateTexture` is false.
+         */
+        public update(): void {
+            if (!this.autoUpdateTexture) {
+                // Expecting user to call `updateTexture` manually
+                return;
+            }
 
-            if (now - this._lastUpdate < 15 || this.video.readyState !== this.video.HAVE_ENOUGH_DATA) {
-                return false;
+            this.updateTexture(true);
+        }
+
+        /**
+         * Update Texture in `manual` mode. Does not do anything if not visible or paused.
+         * @param isVisible Visibility state, detected by user using `scene.getActiveMeshes()` or othervise.
+         */
+        public updateTexture(isVisible: boolean): void {
+            if (!isVisible) {
+                return;
+            }
+            if (this.video.paused) {
+                return;
+            }
+            this._updateInternalTexture();
+        }
+
+        protected _updateInternalTexture = (e?: Event): void => {
+            if (this._texture == null || !this._texture.isReady) {
+                return;
+            }
+            if (this.video.readyState < this.video.HAVE_CURRENT_DATA) {
+                return;
             }
 
-            this._lastUpdate = now;
             this._engine.updateVideoTexture(this._texture, this.video, this._invertY);
-            return true;
+        };
+
+        /**
+         * Change video content. Changing video instance or setting multiple urls (as in constructor) is not supported.
+         * @param url New url.
+         */
+        public updateURL(url: string): void {
+            this.video.src = url;
         }
 
         public dispose(): void {
             super.dispose();
-            this.video.removeEventListener("playing", this._setTextureReady);
+            this.video.removeEventListener("canplay", this._createInternalTexture);
+            this.video.removeEventListener("paused", this._updateInternalTexture);
+            this.video.removeEventListener("seeked", this._updateInternalTexture);
+            this.video.removeEventListener("emptied", this.reset);
         }
 
-        public static CreateFromWebCam(scene: Scene, onReady: (videoTexture: VideoTexture) => void, constraints: {
-            minWidth: number,
-            maxWidth: number,
-            minHeight: number,
-            maxHeight: number,
-            deviceId: string
-        }): void {
+        public static CreateFromWebCam(
+            scene: Scene,
+            onReady: (videoTexture: VideoTexture) => void,
+            constraints: {
+                minWidth: number;
+                maxWidth: number;
+                minHeight: number;
+                maxHeight: number;
+                deviceId: string;
+            }
+        ): void {
             var video = document.createElement("video");
             var constraintsDeviceId;
             if (constraints && constraints.deviceId) {
                 constraintsDeviceId = {
-                    exact: constraints.deviceId
-                }
+                    exact: constraints.deviceId,
+                };
             }
 
-            navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+            navigator.getUserMedia =
+                navigator.getUserMedia ||
+                navigator.webkitGetUserMedia ||
+                navigator.mozGetUserMedia ||
+                navigator.msGetUserMedia;
             window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
 
             if (navigator.getUserMedia) {
-                navigator.getUserMedia({
-                    video: {
-                        deviceId: constraintsDeviceId,
-                        width: {
-                            min: (constraints && constraints.minWidth) || 256,
-                            max: (constraints && constraints.maxWidth) || 640
+                navigator.getUserMedia(
+                    {
+                        video: {
+                            deviceId: constraintsDeviceId,
+                            width: {
+                                min: (constraints && constraints.minWidth) || 256,
+                                max: (constraints && constraints.maxWidth) || 640,
+                            },
+                            height: {
+                                min: (constraints && constraints.minHeight) || 256,
+                                max: (constraints && constraints.maxHeight) || 480,
+                            },
                         },
-                        height: {
-                            min: (constraints && constraints.minHeight) || 256,
-                            max: (constraints && constraints.maxHeight) || 480
+                    },
+                    (stream: any) => {
+                        if (video.mozSrcObject !== undefined) {
+                            // hack for Firefox < 19
+                            video.mozSrcObject = stream;
+                        } else {
+                            video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
                         }
-                    }
-                }, (stream: any) => {
 
-                    if (video.mozSrcObject !== undefined) { // hack for Firefox < 19
-                        video.mozSrcObject = stream;
-                    } else {
-                        video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
-                    }
-
-                    video.play();
+                        video.play();
 
-                    if (onReady) {
-                        onReady(new VideoTexture("video", video, scene, true, true));
+                        if (onReady) {
+                            onReady(new VideoTexture("video", video, scene, true, true));
+                        }
+                    },
+                    function(e: MediaStreamError) {
+                        Tools.Error(e.name);
                     }
-                }, function (e: MediaStreamError) {
-                    Tools.Error(e.name);
-                });
+                );
             }
         }
     }

+ 49 - 0
src/Math/babylon.math.ts

@@ -126,6 +126,21 @@
         }
 
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color3.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color3
+         */
+        public clampToRef(min: number = 0, max: number = 1, result: Color3): Color3 {
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            return this;
+        }
+
+        /**
          * Returns a new Color3 set with the added values of the current Color3 and of the passed one.  
          */
         public add(otherColor: Color3): Color3 {
@@ -389,6 +404,22 @@
         }
 
         /**
+         * Clamps the rgb values by the min and max values and stores the result into "result".
+         * Returns the unmodified current Color4.
+         * @param min - minimum clamping value.  Defaults to 0
+         * @param max - maximum clamping value.  Defaults to 1
+         * @param result - color to store the result into.
+         * @returns - the original Color4
+         */
+        public clampToRef(min: number = 0, max: number = 1, result: Color4): Color4 {
+            result.r = BABYLON.Scalar.Clamp(this.r, min, max);
+            result.g = BABYLON.Scalar.Clamp(this.g, min, max);
+            result.b = BABYLON.Scalar.Clamp(this.b, min, max);
+            result.a = BABYLON.Scalar.Clamp(this.a, min, max);
+            return this;
+        }
+
+        /**
           * Multipy an RGBA Color4 value by another and return a new Color4 object
           * @param color The Color4 (RGBA) value to multiply by
           * @returns A new Color4.
@@ -1460,6 +1491,24 @@
         }
 
         /**
+         * Get angle between two vectors.
+         * @param vector0 angle between vector0 and vector1
+         * @param vector1 angle between vector0 and vector1
+         * @param normal direction of the normal.
+         * @return the angle between vector0 and vector1.
+         */
+        public static GetAngleBetweenVectors(vector0: Vector3, vector1: Vector3, normal: Vector3):number {
+            var v0:Vector3 = vector0.clone().normalize();
+            var v1:Vector3 = vector1.clone().normalize();
+            var dot:number = Vector3.Dot(v0, v1);
+            var n = Vector3.Cross(v0, v1);
+            if (Vector3.Dot(n, normal) > 0) {
+                return Math.acos(dot);
+            }
+            return -Math.acos(dot);
+        }
+
+        /**
          * Returns a new Vector3 set from the index "offset" of the passed array.
          */
         public static FromArray(array: ArrayLike<number>, offset?: number): Vector3 {

+ 2 - 0
src/Mesh/babylon.abstractMesh.ts

@@ -539,6 +539,8 @@
                 return;
             }
             this._lightSources.splice(index, 1);
+
+            this._markSubMeshesAsLightDirty();
         }
 
         private _markSubMeshesAsDirty(func: (defines: MaterialDefines) => void) {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 601 - 35
src/Mesh/babylon.geometry.ts


+ 11 - 3
src/Mesh/babylon.mesh.ts

@@ -297,6 +297,14 @@
             return this._LODLevels.length > 0;
         }
 
+        /**
+         * Gets the list of {BABYLON.MeshLODLevel} associated with the current mesh
+         * @returns an array of {BABYLON.MeshLODLevel} 
+         */
+        public getLODLevels(): MeshLODLevel[] {
+            return this._LODLevels;
+        }
+
         private _sortLODLevels(): void {
             this._LODLevels.sort((a, b) => {
                 if (a.distance < b.distance) {
@@ -767,7 +775,7 @@
             var data = this.getVerticesData(VertexBuffer.PositionKind);
 
             if (data && applySkeleton && this.skeleton) {
-                data = data.slice();
+                data = Tools.Slice(data);
 
                 var matricesIndicesData = this.getVerticesData(VertexBuffer.MatricesIndicesKind);
                 var matricesWeightsData = this.getVerticesData(VertexBuffer.MatricesWeightsKind);
@@ -2492,14 +2500,14 @@
                     mesh._delayInfo.push(VertexBuffer.MatricesWeightsKind);
                 }
 
-                mesh._delayLoadingFunction = Geometry.ImportGeometry;
+                mesh._delayLoadingFunction = Geometry._ImportGeometry;
 
                 if (SceneLoader.ForceFullSceneLoadingForIncremental) {
                     mesh._checkDelayState();
                 }
 
             } else {
-                Geometry.ImportGeometry(parsedMesh, mesh);
+                Geometry._ImportGeometry(parsedMesh, mesh);
             }
 
             // Material

+ 1 - 0
src/Mesh/babylon.vertexBuffer.ts

@@ -145,6 +145,7 @@
 
         /**
          * Updates the underlying WebGLBuffer according to the passed numeric array or Float32Array.  
+         * This function will create a new buffer if the current one is not updatable
          * Returns the updated WebGLBuffer.  
          */
         public update(data: FloatArray): void {

+ 0 - 0
src/Particles/babylon.boxParticleEmitter.ts


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä