Browse Source

Merge remote-tracking branch 'BabylonJS/master'

MackeyK24 7 years ago
parent
commit
80b2c2f445
100 changed files with 27318 additions and 24810 deletions
  1. 9788 9788
      Playground/babylon.d.txt
  2. 5 0
      Playground/frame.css
  3. 3 0
      Playground/frame.html
  4. BIN
      Playground/textures/Flare2.png
  5. BIN
      Playground/textures/Space/space_back.jpg
  6. BIN
      Playground/textures/Space/space_down.jpg
  7. BIN
      Playground/textures/Space/space_front.jpg
  8. BIN
      Playground/textures/Space/space_left.jpg
  9. BIN
      Playground/textures/Space/space_right.jpg
  10. BIN
      Playground/textures/Space/space_up.jpg
  11. BIN
      Playground/textures/flare3.png
  12. BIN
      Playground/textures/wood.jpg
  13. 1 1
      Tools/Gulp/config.json
  14. 1 0
      Tools/Gulp/package.json
  15. BIN
      Viewer/assets/babylon.woff
  16. BIN
      Viewer/assets/img/BabylonJS_Logo_Small.png
  17. 13 0
      Viewer/assets/templates/default/defaultTemplate.html
  18. 3 3
      Viewer/assets/templates/default/loadingScreen.html
  19. 331 67
      Viewer/assets/templates/default/navbar.html
  20. 2 0
      Viewer/dist/_headers
  21. BIN
      Viewer/dist/assets/environment/Skybox_2.0-256.dds
  22. 3 1
      Viewer/dist/ufoExample.html
  23. 1 0
      Viewer/package.json
  24. 76 19
      Viewer/src/configuration/configuration.ts
  25. 28 19
      Viewer/src/configuration/types/default.ts
  26. 1 1
      Viewer/src/configuration/types/environmentMap.ts
  27. 260 39
      Viewer/src/configuration/types/extended.ts
  28. 3 2
      Viewer/src/eventManager.ts
  29. 2 0
      Viewer/src/index.ts
  30. 6 6
      Viewer/src/labs/viewerLabs.ts
  31. 28 4
      Viewer/src/loader/modelLoader.ts
  32. 19 0
      Viewer/src/loader/plugins/applyMaterialConfig.ts
  33. 0 2
      Viewer/src/loader/plugins/extendedMaterialLoaderPlugin.ts
  34. 2 2
      Viewer/src/loader/plugins/index.ts
  35. 0 39
      Viewer/src/loader/plugins/minecraftLoaderPlugin.ts
  36. 62 12
      Viewer/src/model/modelAnimation.ts
  37. 738 466
      Viewer/src/model/viewerModel.ts
  38. 94 0
      Viewer/src/optimizer/custom/extended.ts
  39. 20 0
      Viewer/src/optimizer/custom/index.ts
  40. 31 1
      Viewer/src/templateManager.ts
  41. 149 68
      Viewer/src/viewer/defaultViewer.ts
  42. 396 123
      Viewer/src/viewer/sceneManager.ts
  43. 11 7
      Viewer/src/viewer/viewer.ts
  44. 4 4
      Viewer/tests/unit/src/viewer/viewer.ts
  45. 5 1
      Viewer/tests/unit/webpack.config.js
  46. 5 1
      Viewer/webpack.config.js
  47. 5 1
      Viewer/webpack.gulp.config.js
  48. 12022 12022
      dist/preview release/babylon.d.ts
  49. 17 17
      dist/preview release/babylon.js
  50. 87 98
      dist/preview release/babylon.max.js
  51. 87 98
      dist/preview release/babylon.no-module.max.js
  52. 17 17
      dist/preview release/babylon.worker.js
  53. 87 98
      dist/preview release/es6.js
  54. 1 1
      dist/preview release/gltf2Interface/package.json
  55. 1 1
      dist/preview release/gui/package.json
  56. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  57. 6 0
      dist/preview release/inspector/babylon.inspector.d.ts
  58. 6 0
      dist/preview release/inspector/babylon.inspector.js
  59. 4 4
      dist/preview release/inspector/babylon.inspector.min.js
  60. 1 1
      dist/preview release/inspector/package.json
  61. 2 4
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  62. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  63. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  64. 17 17
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  65. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  66. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  67. 17 17
      dist/preview release/loaders/babylon.glTFFileLoader.js
  68. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  69. 1 1
      dist/preview release/loaders/babylonjs.loaders.d.ts
  70. 17 17
      dist/preview release/loaders/babylonjs.loaders.js
  71. 4 4
      dist/preview release/loaders/babylonjs.loaders.min.js
  72. 1 1
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  73. 2 2
      dist/preview release/loaders/package.json
  74. 1 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.js
  75. 1 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.min.js
  76. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.js
  77. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  78. 1 1
      dist/preview release/materialsLibrary/package.json
  79. 1 1
      dist/preview release/postProcessesLibrary/package.json
  80. 1 1
      dist/preview release/proceduralTexturesLibrary/package.json
  81. 2 2
      dist/preview release/serializers/package.json
  82. 143 39
      dist/preview release/viewer/babylon.viewer.d.ts
  83. 34 33
      dist/preview release/viewer/babylon.viewer.js
  84. 2338 1433
      dist/preview release/viewer/babylon.viewer.max.js
  85. 146 42
      dist/preview release/viewer/babylon.viewer.module.d.ts
  86. 2 1
      dist/preview release/viewer/package.json
  87. 59 61
      dist/preview release/what's new.md
  88. 6 0
      inspector/src/properties.ts
  89. 14 15
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  90. 1 1
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  91. 2 5
      loaders/src/glTF/babylon.glTFFileLoader.ts
  92. 1 1
      materialsLibrary/src/cell/cell.fragment.fx
  93. 2 1
      package.json
  94. 1 1
      sandbox/index.css
  95. 1 7
      src/Animations/babylon.animatable.ts
  96. 8 5
      src/Animations/babylon.animationGroup.ts
  97. 28 33
      src/Animations/babylon.runtimeAnimation.ts
  98. 17 13
      src/Cameras/VR/babylon.vrExperienceHelper.ts
  99. 1 1
      src/Engine/babylon.engine.ts
  100. 0 0
      src/Engine/babylon.nullEngine.ts

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


+ 5 - 0
Playground/frame.css

@@ -8,6 +8,11 @@
     touch-action: none;
 }
 
+canvas {
+    border:none !important;
+    outline:none !important;
+}
+
 #fpsLabel {
     position: absolute;
     right: 10px;

+ 3 - 0
Playground/frame.html

@@ -24,9 +24,12 @@
     <meta name="theme-color" content="#ffffff">
 
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+    
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
     <!-- Babylon.js -->
     <script src="https://preview.babylonjs.com/cannon.js"></script>
     <script src="https://preview.babylonjs.com/Oimo.js"></script>
+    <script src="https://preview.babylonjs.com/earcut.min.js"></script>
     <script src="https://preview.babylonjs.com/babylon.js"></script>
     <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
 

BIN
Playground/textures/Flare2.png


BIN
Playground/textures/Space/space_back.jpg


BIN
Playground/textures/Space/space_down.jpg


BIN
Playground/textures/Space/space_front.jpg


BIN
Playground/textures/Space/space_left.jpg


BIN
Playground/textures/Space/space_right.jpg


BIN
Playground/textures/Space/space_up.jpg


BIN
Playground/textures/flare3.png


BIN
Playground/textures/wood.jpg


+ 1 - 1
Tools/Gulp/config.json

@@ -1764,7 +1764,7 @@
                 "name": "babylonjs-viewer",
                 "main": "../../Viewer/src/index.d.ts",
                 "out": "../../dist/preview release/viewer/babylon.viewer.module.d.ts",
-                "prependText": "/// <reference path=\"./babylon.d.ts\"/>\n/// <reference path=\"./babylon.glTF2Interface.d.ts\"/>\n/// <reference path=\"./babylonjs.loaders.d.ts\"/>\n"
+                "prependText": "/// <reference path=\"./babylon.d.ts\"/>\n/// <reference path=\"./babylon.glTF2Interface.d.ts\"/>\n/// <reference path=\"./babylonjs.loaders.d.ts\"/>\ndeclare module \"babylonjs-loaders\"{ export=BABYLON;}\n"
             },
             "outputs": [
                 {

+ 1 - 0
Tools/Gulp/package.json

@@ -10,6 +10,7 @@
     "license": "(Apache-2.0)",
     "devDependencies": {
         "@types/node": "^8.9.4",
+        "base64-font-loader": "0.0.4",
         "base64-image-loader": "^1.2.1",
         "chai": "^4.1.2",
         "color-support": "^1.1.3",

BIN
Viewer/assets/babylon.woff


BIN
Viewer/assets/img/BabylonJS_Logo_Small.png


+ 13 - 0
Viewer/assets/templates/default/defaultTemplate.html

@@ -1,3 +1,16 @@
+<style>
+    @font-face {
+        font-family: 'babylon';
+        src: url('{{babylonFont}}') format('woff');
+        font-weight: normal;
+        font-style: normal;
+    }
+
+    .icon {
+        font-family: "babylon";
+    }
+</style>
+
 <viewer></viewer>
 <loading-screen></loading-screen>
 <overlay></overlay>

+ 3 - 3
Viewer/assets/templates/default/loadingScreen.html

@@ -10,9 +10,9 @@
         display: flex;
         justify-content: center;
         align-items: center;
-        -webkit-transition: opacity 2s ease;
-        -moz-transition: opacity 2s ease;
-        transition: opacity 2s ease;
+        -webkit-transition: opacity 1s ease;
+        -moz-transition: opacity 1s ease;
+        transition: opacity 1s ease;
     }
 
     img.loading-image {

+ 331 - 67
Viewer/assets/templates/default/navbar.html

@@ -1,79 +1,304 @@
 <style>
     nav-bar {
         position: absolute;
-        height: 160px;
+        height: 48px;
         width: 100%;
-        bottom: 0;
-        background-color: rgba(0, 0, 0, 0.3);
+        bottom: 10px;
+        display: flex;
+        justify-content: center;
+    }
+
+    nav-bar .nav-container {
+        display: flex;
+        flex-direction: row;
+        margin: 0 10px;
+        height: 100%;
+        width: 100%;
+        justify-content: center;
+    }
+
+    nav-bar .animation-control {
+        background-color: rgba(91, 93, 107, .75);
+        display: flex;
+        flex-direction: row;
+        height: 100%;
+        width: 100%;
+        max-width: 1280px;
+        justify-content: center;
+    }
+
+    nav-bar .flex-container {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        height: 100%;
+        width: 100%;
+    }
+
+    nav-bar button {
+        background: none;
+        border: none;
         color: white;
-        transition: 1s;
-        align-items: flex-start;
-        justify-content: space-around;
+        margin: 0;
+        padding: 0;
+
+        height: 100%;
+        min-width: 48px;
+        cursor: pointer;
+    }
+
+    nav-bar button:hover,
+    nav-bar button:active,
+    nav-bar button:focus {
+        background: none;
+        border: none;
+        outline: none;
+    }
+
+    nav-bar button:hover {
+        background-color: rgba(22, 24, 26, .20);
+    }
+
+    nav-bar .control-text {
+        font-family: "Segoe UI";
+        font-size: 12px;
+        font-weight: 400;
+        pointer-events: none;
+    }
+
+    nav-bar img,
+    nav-bar .icon {
+        pointer-events: none;
+    }
+
+    .logo-button {
         display: flex;
+        align-items: center;
+        flex-direction: row;
+        justify-content: center;
+        background-color: rgba(91, 93, 107, .75);
+        height: 48px;
+        min-width: 48px;
+        margin-right: 4px;
+    }
 
+    .logo-button img {
+        height: 20px;
+        width: 20px;
+    }
+
+    .types {
+        display: flex;
         flex-direction: column;
+        width: 48px;
     }
 
-    /* Big screens have room for the entire navbar */
+    .types .flex-container,
+    .speed .flex-container {
+        align-items: center;
+    }
 
-    @media screen and (min-width: 768px) {
-        nav-bar {
-            align-items: center;
-            flex-direction: row;
-            justify-content: space-between;
-            height: 80px;
-        }
+    .menu-options {
+        position: absolute;
+        bottom: 48px;
+        width: 48px;
+        background-color: rgba(22, 24, 26, .90);
+    }
+
+    .logo-button,
+    .animation-label,
+    .types-icon,
+    .help,
+    .speed {
+        display: none;
+    }
+
+    .types-icon:after {
+        font-size: 16px;
+        content: "\F6BE";
+    }
+
+    .up-icon:after {
+        line-height: 16px;
+        font-size: 12px;
+        content: "\E70E";
+    }
+
+    .play-icon:after {
+        font-size: 16px;
+        content: "\E768";
+    }
+
+    .pause-icon:after {
+        font-size: 16px;
+        content: "\E769";
     }
 
-    div.flex-container {
+    .fullscreen-icon:after {
+        font-size: 16px;
+        content: "\E740";
+    }
+
+    .help-icon:after {
+        /* TODO: wrong Icon, need font update */
+        font-size: 16px;
+        content: "\F70C";
+    }
+
+    .progress-control {
         display: flex;
-        width: 100%;
+        flex: 1;
+        position: relative;
+        overflow: hidden;
+        cursor: pointer;
     }
 
-    div.thumbnail {
+    .progress-bar-container {
         position: relative;
         overflow: hidden;
-        display: block;
-        width: 40px;
-        height: 40px;
-        background-size: cover;
-        background-position: center;
-        border-radius: 20px;
-        margin: 0 10px;
     }
 
-    div.title-container {
-        flex-direction: column;
-        display: flex;
-        justify-content: space-between;
+    .progress-bar {
+        align-self: center;
+        flex: 1;
+        background-color: rgb(255, 255, 255);
+        height: 2px;
+        position: absolute;
+        width: 100%;
+        right: 0;
+        pointer-events: none;
     }
 
-    span.model-title {
-        font-size: 125%;
+    .animation-number {
+        margin: 0 6px;
     }
 
-    span.model-subtitle {
-        font-size: 90%;
+    .speed-text {
+        margin-right: 6px;
     }
 
-    div.button-container,
-    div.animation-container {
-        align-items: center;
-        justify-content: flex-end;
+    .progress-wrapper {
+        height: 0px;
+        background-color: rgba(91, 93, 107, .75);
+        width: 100%;
+        border-top: 2px solid rgba(204, 210, 214, .4);
     }
 
-    div.button {
+    .progress-circle {
+        width: 12px;
+        height: 12px;
+        border: 2px solid rgb(255, 255, 255);
+        border-radius: 50%;
+        background-color: rgb(91, 93, 107);
         cursor: pointer;
-        height: 30px;
-        margin: 0 10px;
+        position: relative;
+        bottom: 10px;
+        pointer-events: none;
     }
 
-    div.button img {
+    .default-control {
+        display: flex;
+        flex-direction: row;
         height: 100%;
+        background-color: rgba(91, 93, 107, .75);
+    }
+
+    .menu-options button {
+        width: 100%;
+        height: 48px;
+        color: rgb(142, 147, 155);
+    }
+
+    .menu-options button {
+        width: 100%;
+        height: 48px;
+        color: rgb(142, 147, 155);
+    }
+
+    .menu-options button:hover {
+        background-color: transparent;
+        color: rgb(255, 255, 255);
+    }
+
+    .menu-options .animation-number {
+        margin: 0 18px 0 6px;
+    }
+
+    .menu-options .speed-text {
+        margin-right: 18px;
+    }
+
+    .menu-options {
+        visibility: hidden;
+    }
+
+    .open .menu-options {
+        visibility: visible;
+    }
+
+    @media screen and (min-width: 540px) {
+        .help,
+        .types-icon,
+        .speed {
+            display: inline-block;
+        }
+
+        .logo-button {
+            display: flex;
+        }
+
+        .types {
+            width: 84px;
+        }
+
+        .progress-bar-container {
+            margin: 0 12px;
+        }
+
+        .types .menu-options {
+            width: 84px;
+        }
+        .speed {
+            width: 64px;
+        }
+
+        .speed .menu-options {
+            width: 64px;
+        }
+    }
+
+    @media screen and (min-width: 1024px) {
+        .animation-label {
+            display: block;
+            margin-left: 6px;
+        }
+
+        .progress-bar-container {
+            margin: 0 12px;
+        }
+
+        .types {
+            width: 144px;
+        }
+        .types .menu-options {
+            width: 144px;
+        }
     }
 </style>
 
-{{#if disableOnFullscreen}}
+{{#if (or (not animations) hideAnimations)}} {{#if hideLogo}}
+<style>
+    nav-bar .nav-container {
+        justify-content: flex-end;
+    }
+</style>
+{{else}}
+<style>
+    nav-bar .nav-container {
+        justify-content: space-between;
+    }
+</style>
+{{/if}} {{/if}} {{#if disableOnFullscreen}}
 <style>
     viewer:fullscreen nav-bar {
         display: none;
@@ -89,33 +314,72 @@
 </style>
 {{/if}}
 
-<div class="flex-container" id="model-metadata">
-    <!-- holding the description -->
-    <div class="thumbnail">
-        <!-- holding the thumbnail 
-        <img src="{{thumbnail}}" alt="{{title}}">-->
+<div class="nav-container" id="navbar-control">
+    {{#unless hideLogo}}
+    <div class="logo-button" title="{{logoText}}">
+        <img src="{{logoImg}}">
     </div>
-    <div class="title-container">
-
-        <span class="model-title">{{#if title}}{{title}}{{/if}}</span>
-        <span class="model-subtitle"> {{#if subtitle}}{{subtitle}} {{/if}}</span>
+    {{/unless}} {{#unless (or (not animations) hideAnimations)}}
+    <div class="animation-control">
+        <div class="types">
+            <button class="flex-container" id="types-button">
+                <span class="icon types-icon"></span>
+                <span class="control-text animation-label">Animation</span>
+                <span class="control-text animation-number">{{selectedAnimation}}</span>
+                {{#if (gt (count animations) 1)}}
+                <span class="icon up-icon"></span>
+                {{/if}}
+            </button>
+            <div class="menu-options">
+                {{#each animations}} {{#unless (eq ../selectedAnimation (add @index 1))}}
+                <button class="flex-container" id="label-option-button" data-value="{{this}}">
+                    <span class="icon types-icon"></span>
+                    <span class="control-text animation-label">Animation</span>
+                    <span class="control-text animation-number">{{add @index 1}}</span>
+                </button>
+                {{/unless}} {{/each}}
+            </div>
+        </div>
+        <div class="progress-control" id="progress-control">
+            <button class="play-pause" id="play-pause-button">
+                {{#if paused}}
+                <span class="icon play-icon"></span>
+                {{else}}
+                <span class="icon pause-icon"></span>
+                {{/if}}
+            </button>
+            <div class="progress-bar-container flex-container" id="progress-bar-container">
+                <div class="progress-bar">
+                    <div class="progress-wrapper" id="progress-wrapper">
+                        <div class="progress-circle" id="progress-circle"></div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="speed">
+            <button class="flex-container" id="speed-button">
+                <span class="control-text speed-text">{{selectedSpeed}}</span>
+                <span class="icon up-icon"></span>
+            </button>
+            <div class="menu-options">
+                {{#eachInMap speedList}} {{#unless (eq ../selectedSpeed id)}}
+                <button class="flex-container" id="speed-option-button" data-value="{{value}}">
+                    <span class="control-text speed-text">{{id}}</span>
+                </button>
+                {{/unless}} {{/eachInMap}}
+            </div>
+        </div>
     </div>
-</div>
-{{#if animations}} {{#if hideAnimations}}{{else}}
-<div class="animation-container flex-container">
-    <select id="animation-selector" name="animations">
-        {{#each animations}}
-        <option value="{{this}}">{{this}}</option>> {{/each}}
-    </select>
-</div>
-{{/if}} {{/if}}
-<div class="button-container flex-container">
-    <!-- holding the buttons -->
-    {{#eachInMap buttons}}
-    <div id="{{id}}" class="button">
-        {{#if text}}
-        <span>{{text}}</span>> {{/if}} {{#if image}}
-        <img src="{{image}}" alt="{{altText}}"> {{/if}}
+    {{/unless}}
+    <div class="default-control">
+        {{#unless hideHelp}}
+        <button class="help" id="help-button" title="Help">
+            <span class="icon help-icon"></span>
+        </button>
+        {{/unless}} {{#unless hideFullScreen}}
+        <button class="fullscreen" id="fullscreen-button" title="Fullscreen">
+            <span class="icon fullscreen-icon"></span>
+        </button>
+        {{/unless}}
     </div>
-    {{/eachInMap}}
 </div>

+ 2 - 0
Viewer/dist/_headers

@@ -0,0 +1,2 @@
+/*
+	Access-Control-Allow-Origin: *

BIN
Viewer/dist/assets/environment/Skybox_2.0-256.dds


+ 3 - 1
Viewer/dist/ufoExample.html

@@ -20,8 +20,10 @@
     <body>
         <babylon extends="default, shadowDirectionalLight, environmentMap" templates.nav-bar.params.hide-animations="true" templates.nav-bar.params.disable-on-fullscreen="true">
             <scene glow="true">
-                <main-color r="0.5" g="0.2" b="0.2"></main-color>
             </scene>
+            <lab>
+                <environment-main-color r="0.5" g="0.2" b="0.2"></environment-main-color>
+            </lab>
             <model url="https://models.babylonjs.com/ufo.glb">
                 <animation auto-start="true"></animation>
             </model>

+ 1 - 0
Viewer/package.json

@@ -24,6 +24,7 @@
     "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
     "devDependencies": {
         "@types/node": "^8.9.4",
+        "base64-font-loader": "0.0.4",
         "base64-image-loader": "^1.2.1",
         "html-loader": "^0.5.5",
         "json-loader": "^0.5.7",

+ 76 - 19
Viewer/src/configuration/configuration.ts

@@ -1,5 +1,19 @@
 import { ITemplateConfiguration } from './../templateManager';
-import { EngineOptions, IGlowLayerOptions } from 'babylonjs';
+import { EngineOptions, IGlowLayerOptions, DepthOfFieldEffectBlurLevel } from 'babylonjs';
+
+export function getConfigurationKey(key: string, configObject: any) {
+    let splits = key.split('.');
+
+    if (splits.length === 0 || !configObject) return false;
+    else if (splits.length === 1) {
+        if (configObject[key] !== undefined) {
+            return configObject[key];
+        }
+    } else {
+        let firstKey = splits.shift();
+        return getConfigurationKey(splits.join("."), configObject[firstKey!])
+    }
+}
 
 export interface ViewerConfiguration {
 
@@ -32,6 +46,7 @@ export interface ViewerConfiguration {
     lights?: { [name: string]: boolean | ILightConfiguration },
     // engine configuration. optional!
     engine?: {
+        renderInBackground?: boolean;
         antialiasing?: boolean;
         disableResize?: boolean;
         engineOptions?: EngineOptions;
@@ -73,7 +88,8 @@ export interface ViewerConfiguration {
             specular?: { r: number, g: number, b: number };
         }
         hideLoadingDelay?: number;
-        environmentAssetsRootURL?: string;
+        assetsRootURL?: string;
+        environmentMainColor?: { r: number, g: number, b: number };
         environmentMap?: {
             /**
              * Environment map texture path in relative to the asset folder.
@@ -90,30 +106,67 @@ export interface ViewerConfiguration {
              */
             tintLevel: number;
         }
-        renderingPipelines?: {
-            default?: boolean | {
-                [propName: string]: any;
-            };
-            standard?: boolean | {
-                [propName: string]: any;
-            };
-            /*lens?: boolean | {
-                [propName: string]: boolean | string | number | undefined;
-            };*/
-            ssao?: boolean | {
-                [propName: string]: any;
-            };
-            ssao2?: boolean | {
-                [propName: string]: any;
-            };
-        }
+        defaultRenderingPipelines?: boolean | IDefaultRenderingPipelineConfiguration;
     }
 }
 
+/**
+ * Defines an animation to be applied to a model (translation, scale or rotation).
+ */
+export interface IModelAnimationConfiguration {
+    /**
+     * Time of animation, in seconds
+     */
+    time?: number;
+
+    /**
+     * Scale to apply
+     */
+    scaling?: {
+        x: number;
+        y: number;
+        z: number;
+    };
+
+    /**
+     * Easing function to apply
+     * See SPECTRE.EasingFunction
+     */
+    easingFunction?: number;
+
+    /**
+     * An Easing mode to apply to the easing function
+     * See BABYLON.EasingFunction
+     */
+    easingMode?: number;
+}
+
+
+export interface IDefaultRenderingPipelineConfiguration {
+    sharpenEnabled?: boolean;
+    bloomEnabled?: boolean;
+    bloomThreshold?: number;
+    depthOfFieldEnabled?: boolean;
+    depthOfFieldBlurLevel?: DepthOfFieldEffectBlurLevel;
+    fxaaEnabled?: boolean;
+    imageProcessingEnabled?: boolean;
+    defaultPipelineTextureType?: number;
+    bloomScale?: number;
+    chromaticAberrationEnabled?: boolean;
+    grainEnabled?: boolean;
+    bloomKernel?: number;
+    hardwareScaleLevel?: number;
+    bloomWeight?: number;
+    bllomThreshold?: number;
+    hdr?: boolean;
+    samples?: number;
+}
+
 export interface IModelConfiguration {
     id?: string;
     url?: string;
     root?: string; //optional
+    file?: string; // is a file being loaded? root and url ignored
     loader?: string; // obj, gltf?
     position?: { x: number, y: number, z: number };
     rotation?: { x: number, y: number, z: number, w?: number };
@@ -137,6 +190,9 @@ export interface IModelConfiguration {
         playOnce?: boolean;
     }
 
+    entryAnimation?: IModelAnimationConfiguration;
+    exitAnimation?: IModelAnimationConfiguration;
+
     material?: {
         directEnabled?: boolean;
         directIntensity?: number;
@@ -358,6 +414,7 @@ export interface ISceneOptimizerConfiguration {
         renderTarget?: ISceneOptimizerParameters;
         mergeMeshes?: ISceneOptimizerParameters;
     }
+    custom?: string;
 }
 
 export interface IObserversConfiguration {

+ 28 - 19
Viewer/src/configuration/types/default.ts

@@ -4,7 +4,11 @@ export let defaultConfiguration: ViewerConfiguration = {
     version: "3.2.0-alpha4",
     templates: {
         main: {
-            html: require("../../../assets/templates/default/defaultTemplate.html")
+            html: require("../../../assets/templates/default/defaultTemplate.html"),
+            params: {
+                babylonFont: require('../../../assets/babylon.woff'),
+                noEscape: true
+            }
         },
         loadingScreen: {
             html: require("../../../assets/templates/default/loadingScreen.html"),
@@ -24,22 +28,23 @@ export let defaultConfiguration: ViewerConfiguration = {
         navBar: {
             html: require("../../../assets/templates/default/navbar.html"),
             params: {
-                buttons: {
-                    /*"help-button": {
-                        altText: "Help",
-                        image: require('../../../assets/img/help-circle.png')
-                    },*/
-                    "fullscreen-button": {
-                        altText: "Fullscreen",
-                        image: require('../../../assets/img/fullscreen.png')
-                    }
+                speedList: {
+                    "0.5x": "0.5",
+                    "1.0x": "1.0",
+                    "1.5x": "1.5",
+                    "2.0x": "2.0",
                 },
-                visibilityTimeout: 2000
+                logoImg: require('../../../assets/img/BabylonJS_Logo_Small.png'),
+                logoText: 'BabylonJS',
+                hideHelp: true,
+                disableOnFullscreen: true,
             },
             events: {
-                pointerdown: { 'fullscreen-button': true/*, '#help-button': true*/ },
+                pointerdown: {
+                    'navbar-control': true,
+                    'help-button': true
+                },
                 pointerover: true,
-                change: { 'animation-selector': true }
             }
         },
         overlay: {
@@ -62,13 +67,17 @@ export let defaultConfiguration: ViewerConfiguration = {
     },
     camera: {
         behaviors: {
-            autoRotate: 0,
+            autoRotate: {
+                type: 0
+            },
             framing: {
                 type: 2,
                 zoomOnBoundingInfo: true,
                 zoomStopsAnimation: false
             },
-            bouncing: 1
+            bouncing: {
+                type: 1
+            }
         },
         wheelPrecision: 200,
     },
@@ -77,9 +86,9 @@ export let defaultConfiguration: ViewerConfiguration = {
             url: 'https://playground.babylonjs.com/textures/environment.dds',
             gammaSpace: false
         },*/
-        pbr: true,
+        /*pbr: true,
         blur: 0.7,
-        infiniteDistance: false,
+        infiniteDistance: false,*/
         /*material: {
             imageProcessingConfiguration: {
                 colorCurves: {
@@ -105,10 +114,10 @@ export let defaultConfiguration: ViewerConfiguration = {
         antialiasing: true
     },
     scene: {
-        imageProcessingConfiguration: {
+        /*imageProcessingConfiguration: {
             exposure: 1.4,
             contrast: 1.66,
             toneMappingEnabled: true
-        }
+        }*/
     }
 }

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

@@ -2,7 +2,7 @@ import { ViewerConfiguration } from './../configuration';
 
 export const environmentMapConfiguration: ViewerConfiguration = {
     lab: {
-        environmentAssetsRootURL: '/assets/environment/',
+        assetsRootURL: '/assets/environment/',
         environmentMap: {
             texture: 'EnvMap_2.0-256.env',
             rotationY: 0,

+ 260 - 39
Viewer/src/configuration/types/extended.ts

@@ -1,93 +1,314 @@
 import { ViewerConfiguration } from './../configuration';
+import { Tools } from 'babylonjs';
 
 export let extendedConfiguration: ViewerConfiguration = {
     version: "3.2.0",
     extends: "default",
     camera: {
+        exposure: 3.034578,
+        fov: 0.7853981633974483,
+        contrast: 1.6,
+        toneMappingEnabled: true,
+        upperBetaLimit: 1.3962634015954636 + Math.PI / 2,
+        lowerBetaLimit: -1.4835298641951802 + Math.PI / 2,
+        behaviors: {
+            framing: {
+                type: 2,
+                mode: 0,
+                positionScale: 0.5,
+                defaultElevation: 0.2617993877991494,
+                elevationReturnWaitTime: 3000,
+                elevationReturnTime: 2000,
+                framingTime: 500,
+                zoomStopsAnimation: false,
+                radiusScale: 0.866
+            },
+            autoRotate: {
+                type: 0,
+                idleRotationWaitTime: 4000,
+                idleRotationSpeed: 0.17453292519943295,
+                idleRotationSpinupTime: 2500,
+                zoomStopsAnimation: false
+            },
+            bouncing: {
+                type: 1,
+                lowerRadiusTransitionRange: 0.05,
+                upperRadiusTransitionRange: -0.2
+            }
+        },
+        upperRadiusLimit: 5,
+        lowerRadiusLimit: 0.5,
+        frameOnModelLoad: true,
+        framingElevation: 0.2617993877991494,
+        framingRotation: 1.5707963267948966,
         radius: 2,
-        alpha: -1.5708,
+        alpha: 1.5708,
         beta: Math.PI * 0.5 - 0.2618,
         wheelPrecision: 300,
         minZ: 0.1,
         maxZ: 50,
+        fovMode: 0,
+        pinchPrecision: 1500,
+        panningSensibility: 3000
     },
     lights: {
-        "light1": {
+        light0: {
             type: 0,
-            shadowEnabled: false,
-            position: { x: -1.78, y: 2.298, z: 2.62 },
-            diffuse: { r: 0.8, g: 0.8, b: 0.8 },
-            intensity: 3,
+            frustumEdgeFalloff: 0,
+            intensity: 7,
             intensityMode: 0,
-            radius: 3.135,
+            radius: 0.6,
+            range: 0.6,
+            spotAngle: 60,
+            diffuse: {
+                r: 1,
+                g: 1,
+                b: 1
+            },
+            position: {
+                x: -2,
+                y: 2.5,
+                z: 2
+            },
+            target: {
+                x: 0,
+                y: 0,
+                z: 0
+            },
+            enabled: true,
+            shadowEnabled: true,
+            shadowBufferSize: 512,
+            shadowMinZ: 1,
+            shadowMaxZ: 10,
+            shadowFieldOfView: 60,
+            shadowFrustumSize: 2,
+            shadowConfig: {
+                useBlurCloseExponentialShadowMap: true,
+                useKernelBlur: true,
+                blurScale: 1.0,
+                bias: 0.001,
+                depthScale: 50 * (10 - 1),
+                frustumEdgeFalloff: 0
+            }
         },
-        "light3": {
-            type: 2,
+        light1: {
+            type: 0,
+            frustumEdgeFalloff: 0,
+            intensity: 7,
+            intensityMode: 0,
+            radius: 0.4,
+            range: 0.4,
+            spotAngle: 57,
+            diffuse: {
+                r: 1,
+                g: 1,
+                b: 1
+            },
+            position: {
+                x: 4,
+                y: 3,
+                z: -0.5
+            },
+            target: {
+                x: 0,
+                y: 0,
+                z: 0
+            },
+            enabled: true,
             shadowEnabled: false,
-            position: { x: -4, y: 2, z: -2.23 },
-            diffuse: { r: 0.718, g: 0.772, b: 0.749 },
-            intensity: 2.052,
+            shadowBufferSize: 512,
+            shadowMinZ: 0.2,
+            shadowMaxZ: 10,
+            shadowFieldOfView: 28,
+            shadowFrustumSize: 2
+        },
+        light2: {
+            type: 0,
+            frustumEdgeFalloff: 0,
+            intensity: 1,
             intensityMode: 0,
             radius: 0.5,
-            spotAngle: 42.85
+            range: 0.5,
+            spotAngle: 42.85,
+            diffuse: {
+                r: 0.8,
+                g: 0.8,
+                b: 0.8
+            },
+            position: {
+                x: -1,
+                y: 3,
+                z: -3
+            },
+            target: {
+                x: 0,
+                y: 0,
+                z: 0
+            },
+            enabled: true,
+            shadowEnabled: false,
+            shadowBufferSize: 512,
+            shadowMinZ: 0.2,
+            shadowMaxZ: 10,
+            shadowFieldOfView: 45,
+            shadowFrustumSize: 2
         }
     },
     ground: {
-        receiveShadows: true
+        shadowLevel: 0.9,
+        texture: "Ground_2.0-1024.png",
+        material: {
+            primaryColorHighlightLevel: 0.035,
+            primaryColorShadowLevel: 0,
+            enableNoise: true,
+            useRGBColor: false,
+            maxSimultaneousLights: 1,
+            diffuseTexture: {
+                gammaSpace: true
+            }
+        },
+        opacity: 1,
+        mirror: false,
+        receiveShadows: true,
+        size: 5
+    },
+    skybox: {
+        scale: 11,
+        cubeTexture: {
+            url: "Skybox_2.0-256.dds"
+        },
+        material: {
+            primaryColorHighlightLevel: 0.03,
+            primaryColorShadowLevel: 0.03,
+            enableNoise: true,
+            useRGBColor: false,
+            reflectionTexture: {
+                gammaSpace: true
+            }
+        }
+    },
+    engine: {
+        renderInBackground: true
     },
     scene: {
+        flags: {
+            shadowsEnabled: true,
+            particlesEnabled: false,
+            collisionsEnabled: false,
+            lightsEnabled: true,
+            texturesEnabled: true,
+            lensFlaresEnabled: false,
+            proceduralTexturesEnabled: false,
+            renderTargetsEnabled: true,
+            spritesEnabled: false,
+            skeletonsEnabled: true,
+            audioEnabled: false,
+        },
+        defaultMaterial: {
+            materialType: 'pbr',
+            reflectivityColor: {
+                r: 0.1,
+                g: 0.1,
+                b: 0.1
+            },
+            microSurface: 0.6
+        },
+        clearColor: {
+            r: 0.9,
+            g: 0.9,
+            b: 0.9,
+            a: 1.0
+        },
         imageProcessingConfiguration: {
+            vignetteCentreX: 0,
+            vignetteCentreY: 0,
+            vignetteColor: {
+                r: 0.086,
+                g: 0.184,
+                b: 0.259,
+                a: 1
+            },
+            vignetteWeight: 0.855,
+            vignetteStretch: 0.5,
+            vignetteBlendMode: 0,
+            vignetteCameraFov: 0.7853981633974483,
+            isEnabled: true,
             colorCurves: {
-                shadowsHue: 43.359,
-                shadowsDensity: 1,
-                shadowsSaturation: -25,
-                shadowsExposure: -3.0,
-                midtonesHue: 93.65,
-                midtonesDensity: -15.24,
-                midtonesExposure: 7.37,
-                midtonesSaturation: -15,
-                highlightsHue: 37.2,
-                highlightsDensity: -22.43,
-                highlightsExposure: 45.0,
-                highlightsSaturation: -15
+                shadowsHue: 0,
+                shadowsDensity: 0,
+                shadowsSaturation: 0,
+                shadowsExposure: 0,
+                midtonesHue: 0,
+                midtonesDensity: 0,
+                midtonesExposure: 0,
+                midtonesSaturation: 0,
+                highlightsHue: 0,
+                highlightsDensity: 0,
+                highlightsExposure: 0,
+                highlightsSaturation: 0
             }
         },
         mainColor: {
-            r: 0.7,
-            g: 0.7,
-            b: 0.7
+            r: 0.8823529411764706,
+            g: 0.8823529411764706,
+            b: 0.8823529411764706
         }
     },
     loaderPlugins: {
         extendedMaterial: true,
-        minecraft: true,
+        applyMaterialConfig: true,
         msftLod: true,
         telemetry: true
     },
     model: {
         rotationOffsetAxis: {
             x: 0,
-            y: 1,
+            y: -1,
             z: 0
         },
-        rotationOffsetAngle: 3.66519,
+        rotationOffsetAngle: Tools.ToRadians(210),
         material: {
             directEnabled: true,
             directIntensity: 0.884,
             emissiveIntensity: 1.04,
-            environmentIntensity: 0.868
+            environmentIntensity: 0.6
+        },
+        entryAnimation: {
+            scaling: {
+                x: 0,
+                y: 0,
+                z: 0
+            },
+            time: 0.5,
+            easingFunction: 4,
+            easingMode: 1
+        },
+        exitAnimation: {
+            scaling: {
+                x: 0,
+                y: 0,
+                z: 0
+            },
+            time: 0.5,
+            easingFunction: 4,
+            easingMode: 1
         },
         normalize: true,
         castShadow: true,
         receiveShadows: true
     },
     lab: {
-        renderingPipelines: {
-            default: {
-                bloomEnabled: true,
-                bloomThreshold: 1.0,
-                fxaaEnabled: true
-            }
+        assetsRootURL: '/assets/environment/',
+        environmentMap: {
+            texture: "EnvMap_2.0-256.env",
+            rotationY: 3,
+            tintLevel: 0.4
+        },
+        defaultRenderingPipelines: {
+            bloomEnabled: true,
+            bloomThreshold: 1.0,
+            fxaaEnabled: true,
+            bloomWeight: 0.05
         }
     }
 }

+ 3 - 2
Viewer/src/eventManager.ts

@@ -30,8 +30,9 @@ export class EventManager {
             this._callbacksContainer[templateName] = [];
         }
         this._callbacksContainer[templateName].push({
-            eventType: eventType,
-            callback: callback
+            eventType,
+            callback,
+            selector
         });
     }
 

+ 2 - 0
Viewer/src/index.ts

@@ -42,5 +42,7 @@ function disposeAll() {
 
 const Version = BABYLON.Engine.Version;
 
+console.log("Babylon.js viewer (v" + Version + ")");
+
 // public API for initialization
 export { BABYLON, Version, InitTags, DefaultViewer, AbstractViewer, viewerGlobals, telemetryManager, disableInit, viewerManager, mapperManager, disposeAll, ModelLoader, ViewerModel, AnimationPlayMode, AnimationState, ModelState, ILoaderPlugin };

+ 6 - 6
Viewer/src/labs/viewerLabs.ts

@@ -9,7 +9,7 @@ export class ViewerLabs {
 
     constructor(private _sceneManager: SceneManager) { }
 
-    public environmentAssetsRootURL: string;
+    public assetsRootURL: string;
     public environment: PBREnvironment = {
         //irradiance
         irradiancePolynomialCoefficients: {
@@ -57,7 +57,7 @@ export class ViewerLabs {
             this.environment = EnvironmentDeserializer.Parse(data);
             if (onSuccess) onSuccess(this.environment);
         } else if (typeof data === 'string') {
-            let url = this.getEnvironmentAssetUrl(data);
+            let url = this.getAssetUrl(data);
             this._sceneManager.scene._loadFile(
                 url,
                 (arrayBuffer: ArrayBuffer) => {
@@ -124,15 +124,15 @@ export class ViewerLabs {
      * @param url Asset url
      * @returns The Asset url using the `environmentAssetsRootURL` if the url is not an absolute path.
      */
-    public getEnvironmentAssetUrl(url: string): string {
+    public getAssetUrl(url: string): string {
         let returnUrl = url;
         if (url && url.toLowerCase().indexOf("//") === -1) {
-            if (!this.environmentAssetsRootURL) {
-                Tools.Warn("Please, specify the root url of your assets before loading the configuration (labs.environmentAssetsRootURL) or disable the background through the viewer options.");
+            if (!this.assetsRootURL) {
+                // Tools.Warn("Please, specify the root url of your assets before loading the configuration (labs.environmentAssetsRootURL) or disable the background through the viewer options.");
                 return url;
             }
 
-            returnUrl = this.environmentAssetsRootURL + returnUrl;
+            returnUrl = this.assetsRootURL + returnUrl;
         }
 
         return returnUrl;

+ 28 - 4
Viewer/src/loader/modelLoader.ts

@@ -63,8 +63,18 @@ export class ModelLoader {
             return model;
         }
 
-        let filename = Tools.GetFilename(modelConfiguration.url) || modelConfiguration.url;
-        let base = modelConfiguration.root || Tools.GetFolderPath(modelConfiguration.url);
+        let base: string;
+        let filename: any;
+        if (modelConfiguration.file) {
+            base = "file:";
+            filename = modelConfiguration.file;
+        }
+        else {
+            filename = Tools.GetFilename(modelConfiguration.url) || modelConfiguration.url;
+            base = modelConfiguration.root || Tools.GetFolderPath(modelConfiguration.url);
+        }
+
+
         let plugin = modelConfiguration.loader;
 
         model.loader = SceneLoader.ImportMesh(undefined, base, filename, this._viewer.sceneManager.scene, (meshes, particleSystems, skeletons, animationGroups) => {
@@ -80,7 +90,9 @@ export class ModelLoader {
             }
 
             this._checkAndRun("onLoaded", model);
-            model.onLoadedObservable.notifyObserversWithPromise(model);
+            this._viewer.sceneManager.scene.executeWhenReady(() => {
+                model.onLoadedObservable.notifyObservers(model);
+            });
         }, (progressEvent) => {
             this._checkAndRun("onProgress", progressEvent);
             model.onLoadProgressObservable.notifyObserversWithPromise(progressEvent);
@@ -95,6 +107,12 @@ export class ModelLoader {
             let gltfLoader = (<GLTFFileLoader>model.loader);
             gltfLoader.animationStartMode = GLTFLoaderAnimationStartMode.NONE;
             gltfLoader.compileMaterials = true;
+
+            if (!modelConfiguration.file) {
+                gltfLoader.rewriteRootURL = (rootURL, responseURL) => {
+                    return modelConfiguration.root || Tools.GetFolderPath(responseURL || modelConfiguration.url || '');
+                };
+            }
             // if ground is set to "mirror":
             if (this._viewer.configuration.ground && typeof this._viewer.configuration.ground === 'object' && this._viewer.configuration.ground.mirror) {
                 gltfLoader.useClipPlane = true;
@@ -109,7 +127,13 @@ export class ModelLoader {
                 if (data && data.json && data.json['asset']) {
                     model.loadInfo = data.json['asset'];
                 }
-            })
+            });
+
+            gltfLoader.onCompleteObservable.add(() => {
+                model.loaderDone = true;
+            });
+        } else {
+            model.loaderDone = true;
         }
 
         this._checkAndRun("onInit", model.loader, model);

+ 19 - 0
Viewer/src/loader/plugins/applyMaterialConfig.ts

@@ -0,0 +1,19 @@
+import { ILoaderPlugin } from "./loaderPlugin";
+import { telemetryManager } from "../../telemetryManager";
+import { ViewerModel } from "../..";
+import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from "babylonjs";
+import { IGLTFLoaderData, GLTF2 } from "babylonjs-loaders";
+
+
+export class ApplyMaterialConfigPlugin implements ILoaderPlugin {
+
+    private _model: ViewerModel;
+
+    public onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel) {
+        this._model = model;
+    }
+
+    public onMaterialLoaded(material: Material) {
+        this._model && this._model._applyModelMaterialConfiguration(material);
+    }
+}

+ 0 - 2
Viewer/src/loader/plugins/extendedMaterialLoaderPlugin.ts

@@ -5,8 +5,6 @@ import { Color3, Texture, BaseTexture, Tools, ISceneLoaderPlugin, ISceneLoaderPl
 
 export class ExtendedMaterialLoaderPlugin implements ILoaderPlugin {
 
-    private _model: ViewerModel;
-
     public onMaterialLoaded(baseMaterial: Material) {
         var material = baseMaterial as PBRMaterial;
         material.alphaMode = Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;

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

@@ -1,7 +1,7 @@
 import { TelemetryLoaderPlugin } from "./telemetryLoaderPlugin";
 import { ILoaderPlugin } from "./loaderPlugin";
 import { MSFTLodLoaderPlugin } from './msftLodLoaderPlugin';
-import { MinecraftLoaderPlugin } from './minecraftLoaderPlugin';
+import { ApplyMaterialConfigPlugin } from './applyMaterialConfig';
 import { ExtendedMaterialLoaderPlugin } from './extendedMaterialLoaderPlugin';
 
 const pluginCache: { [key: string]: ILoaderPlugin } = {};
@@ -15,7 +15,7 @@ export function getLoaderPluginByName(name: string) {
             case 'msftLod':
                 pluginCache[name] = new MSFTLodLoaderPlugin();
                 break;
-            case 'minecraft':
+            case 'applyMaterialConfig':
                 pluginCache[name] = new MSFTLodLoaderPlugin();
                 break;
             case 'extendedMaterial':

+ 0 - 39
Viewer/src/loader/plugins/minecraftLoaderPlugin.ts

@@ -1,39 +0,0 @@
-import { ILoaderPlugin } from "./loaderPlugin";
-import { telemetryManager } from "../../telemetryManager";
-import { ViewerModel } from "../..";
-import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from "babylonjs";
-import { IGLTFLoaderData, GLTF2 } from "babylonjs-loaders";
-
-
-export class MinecraftLoaderPlugin implements ILoaderPlugin {
-
-    private _model: ViewerModel;
-
-    private _minecraftEnabled: boolean;
-
-    public onInit(loader: ISceneLoaderPlugin | ISceneLoaderPluginAsync, model: ViewerModel) {
-        this._model = model;
-        this._minecraftEnabled = false;
-    }
-
-    public inParsed(data: IGLTFLoaderData) {
-        if (data && data.json && data.json['meshes'] && data.json['meshes'].length) {
-            var meshes = data.json['meshes'] as GLTF2.IMesh[];
-            for (var i = 0; i < meshes.length; i++) {
-                var mesh = meshes[i];
-                if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
-                    this._minecraftEnabled = true;
-                    break;
-                }
-            }
-        }
-    }
-
-    public onMaterialLoaded(material: Material) {
-        if (this._minecraftEnabled && material.needAlphaBlending()) {
-            material.forceDepthWrite = true;
-            material.backFaceCulling = true;
-            material.separateCullingPass = true;
-        }
-    }
-}

+ 62 - 12
Viewer/src/model/modelAnimation.ts

@@ -1,9 +1,9 @@
-import { AnimationGroup, Animatable, Skeleton } from "babylonjs";
+import { AnimationGroup, Animatable, Skeleton, Vector3 } from "babylonjs";
 
 /**
  * Animation play mode enum - is the animation looping or playing once
  */
-export enum AnimationPlayMode {
+export const enum AnimationPlayMode {
     ONCE,
     LOOP
 }
@@ -11,7 +11,7 @@ export enum AnimationPlayMode {
 /**
  * An enum representing the current state of an animation object
  */
-export enum AnimationState {
+export const enum AnimationState {
     INIT,
     PLAYING,
     PAUSED,
@@ -20,6 +20,51 @@ export enum AnimationState {
 }
 
 /**
+ * The different type of easing functions available 
+ */
+export const enum EasingFunction {
+    Linear = 0,
+    CircleEase = 1,
+    BackEase = 2,
+    BounceEase = 3,
+    CubicEase = 4,
+    ElasticEase = 5,
+    ExponentialEase = 6,
+    PowerEase = 7,
+    QuadraticEase = 8,
+    QuarticEase = 9,
+    QuinticEase = 10,
+    SineEase = 11
+}
+
+/**
+ * Defines a simple animation to be applied to a model (scale).
+ */
+export interface ModelAnimationConfiguration {
+    /**
+     * Time of animation, in seconds
+     */
+    time: number;
+
+    /**
+     * Scale to apply
+     */
+    scaling?: Vector3;
+
+    /**
+     * Easing function to apply
+     * See SPECTRE.EasingFunction
+     */
+    easingFunction?: number;
+
+    /**
+     * An Easing mode to apply to the easing function
+     * See BABYLON.EasingFunction
+     */
+    easingMode?: number;
+}
+
+/**
  * This interface can be implemented to define new types of ModelAnimation objects.
  */
 export interface IModelAnimation {
@@ -146,11 +191,12 @@ export class GroupModelAnimation implements IModelAnimation {
      * In correlation to an arry, this would be ".length"
      */
     public get frames(): number {
-        let animationFrames = this._animationGroup.targetedAnimations.map(ta => {
+        /*let animationFrames = this._animationGroup.targetedAnimations.map(ta => {
             let keys = ta.animation.getKeys();
             return keys[keys.length - 1].frame;
         });
-        return Math.max.apply(null, animationFrames);
+        return Math.max.apply(null, animationFrames);*/
+        return this._animationGroup.to - this._animationGroup.from;
     }
 
     /**
@@ -161,7 +207,7 @@ export class GroupModelAnimation implements IModelAnimation {
      */
     public get currentFrame(): number {
         // get the first currentFrame found
-        for (let i = 0; i < this._animationGroup.animatables.length; ++i) {
+        /*for (let i = 0; i < this._animationGroup.animatables.length; ++i) {
             let animatable: Animatable = this._animationGroup.animatables[i];
             let animations = animatable.getAnimations();
             if (!animations || !animations.length) {
@@ -172,8 +218,12 @@ export class GroupModelAnimation implements IModelAnimation {
                     return animations[idx].currentFrame;
                 }
             }
+        }*/
+        if (this._animationGroup.targetedAnimations[0] && this._animationGroup.targetedAnimations[0].animation.runtimeAnimations[0]) {
+            return this._animationGroup.targetedAnimations[0].animation.runtimeAnimations[0].currentFrame - this._animationGroup.from;
+        } else {
+            return 0;
         }
-        return 0;
     }
 
     /**
@@ -234,7 +284,10 @@ export class GroupModelAnimation implements IModelAnimation {
      * Restart the animation group
      */
     restart() {
-        this._animationGroup.restart();
+        if (this.state === AnimationState.PAUSED)
+            this._animationGroup.restart();
+        else
+            this.start();
     }
 
     /**
@@ -242,10 +295,7 @@ export class GroupModelAnimation implements IModelAnimation {
      * @param frameNumber Go to a specific frame in the animation
      */
     goToFrame(frameNumber: number) {
-        // this._animationGroup.goToFrame(frameNumber);
-        this._animationGroup['_animatables'].forEach(a => {
-            a.goToFrame(frameNumber);
-        })
+        this._animationGroup.goToFrame(frameNumber + this._animationGroup.from);
     }
 
     /**

File diff suppressed because it is too large
+ 738 - 466
Viewer/src/model/viewerModel.ts


+ 94 - 0
Viewer/src/optimizer/custom/extended.ts

@@ -0,0 +1,94 @@
+import { AbstractViewer } from '../../viewer/viewer';
+import { Scalar, DefaultRenderingPipeline } from 'babylonjs';
+
+export function extendedUpgrade(viewer: AbstractViewer): boolean {
+    let defaultPipeline = <DefaultRenderingPipeline>viewer.sceneManager.defaultRenderingPipeline;
+    // if (!this.Scene.BackgroundHelper) {
+    // 	this.Scene.EngineScene.autoClear = false;
+    // this.Scene.BackgroundHelper = true;
+    // Would require a dedicated clear color;
+    // return false;
+    // }
+    if (viewer.engine.getHardwareScalingLevel() > 1) {
+        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() - 0.25, 0, 1);
+        viewer.engine.setHardwareScalingLevel(scaling);
+        return false;
+    }
+    if (!viewer.sceneManager.scene.postProcessesEnabled) {
+        viewer.sceneManager.scene.postProcessesEnabled = true;
+        return false;
+    }
+    if (!viewer.sceneManager.groundEnabled) {
+        viewer.sceneManager.groundEnabled = true;
+        return false;
+    }
+    if (defaultPipeline && !viewer.sceneManager.fxaaEnabled) {
+        viewer.sceneManager.fxaaEnabled = true
+        return false;
+    }
+    var hardwareScalingLevel = Math.max(1 / 2, 1 / (window.devicePixelRatio || 2));
+    if (viewer.engine.getHardwareScalingLevel() > hardwareScalingLevel) {
+        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() - 0.25, 0, hardwareScalingLevel);
+        viewer.engine.setHardwareScalingLevel(scaling);
+        return false;
+    }
+    if (!viewer.sceneManager.processShadows) {
+        viewer.sceneManager.processShadows = true;
+        return false;
+    }
+    if (defaultPipeline && !viewer.sceneManager.bloomEnabled) {
+        viewer.sceneManager.bloomEnabled = true
+        return false;
+    }
+    if (!viewer.sceneManager.groundMirrorEnabled) {
+        viewer.sceneManager.groundMirrorEnabled = true;
+        return false;
+    }
+    return true;
+}
+
+export function extendedDegrade(viewer: AbstractViewer): boolean {
+    let defaultPipeline = <DefaultRenderingPipeline>viewer.sceneManager.defaultRenderingPipeline;
+
+    if (viewer.sceneManager.groundMirrorEnabled) {
+        viewer.sceneManager.groundMirrorEnabled = false;
+        return false;
+    }
+    if (defaultPipeline && viewer.sceneManager.bloomEnabled) {
+        viewer.sceneManager.bloomEnabled = false;
+        return false;
+    }
+    if (viewer.sceneManager.processShadows) {
+        viewer.sceneManager.processShadows = false;
+        return false;
+    }
+    if (viewer.engine.getHardwareScalingLevel() < 1) {
+        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() + 0.25, 0, 1);
+        viewer.engine.setHardwareScalingLevel(scaling);
+        return false;
+    }
+    if (defaultPipeline && viewer.sceneManager.fxaaEnabled) {
+        viewer.sceneManager.fxaaEnabled = false;
+        return false;
+    }
+    if (viewer.sceneManager.groundEnabled) {
+        viewer.sceneManager.groundEnabled = false;
+        return false;
+    }
+    if (viewer.sceneManager.scene.postProcessesEnabled) {
+        viewer.sceneManager.scene.postProcessesEnabled = false;
+        return false;
+    }
+    if (viewer.engine.getHardwareScalingLevel() < 1.25) {
+        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() + 0.25, 0, 1.25);
+        viewer.engine.setHardwareScalingLevel(scaling);
+        return false;
+    }
+    // if (this.Scene.BackgroundHelper) {
+    // 	this.Scene.EngineScene.autoClear = true;
+    // this.Scene.BackgroundHelper = false;
+    // Would require a dedicated clear color;
+    // return false;
+    // }
+    return true;
+}

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

@@ -0,0 +1,20 @@
+import { AbstractViewer } from "../../viewer/viewer";
+import { extendedUpgrade, extendedDegrade } from "./extended";
+
+const cache: { [key: string]: (viewer: AbstractViewer) => boolean } = {};
+
+export function getCustomOptimizerByName(name: string, upgrade?: boolean) {
+    if (!cache[name]) {
+        switch (name) {
+            case 'extended':
+                if (upgrade) {
+                    return extendedUpgrade;
+                }
+                else {
+                    return extendedDegrade;
+                }
+        }
+    }
+
+    return cache[name];
+}

+ 31 - 1
Viewer/src/templateManager.ts

@@ -241,6 +241,36 @@ Handlebars.registerHelper('eachInMap', function (map, block) {
     return out;
 });
 
+Handlebars.registerHelper('add', function (a, b) {
+    var out = a + b;
+    return out;
+});
+
+Handlebars.registerHelper('eq', function (a, b) {
+    var out = (a == b);
+    return out;
+});
+
+
+Handlebars.registerHelper('or', function (a, b) {
+    var out = a || b;
+    return out;
+});
+
+Handlebars.registerHelper('not', function (a) {
+    var out = !a;
+    return out;
+});
+
+Handlebars.registerHelper('count', function (map) {
+    return map.length;
+});
+
+Handlebars.registerHelper('gt', function (a, b) {
+    var out = a > b;
+    return out;
+});
+
 /**
  * This class represents a single template in the viewer's template tree.
  * An example for a template is a single canvas, an overlay (containing sub-templates) or the navigation bar.
@@ -318,7 +348,7 @@ export class Template {
         this.initPromise = htmlContentPromise.then(htmlTemplate => {
             if (htmlTemplate) {
                 this._htmlTemplate = htmlTemplate;
-                let compiledTemplate = Handlebars.compile(htmlTemplate);
+                let compiledTemplate = Handlebars.compile(htmlTemplate, { noEscape: (this._configuration.params && this._configuration.params.noEscape) });
                 let config = this._configuration.params || {};
                 this._rawHtml = compiledTemplate(config);
                 try {

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

@@ -7,6 +7,7 @@ import { SpotLight, MirrorTexture, Plane, ShadowGenerator, Texture, BackgroundMa
 import { CameraBehavior } from '../interfaces';
 import { ViewerModel } from '../model/viewerModel';
 import { extendClassWithConfig } from '../helper';
+import { IModelAnimation } from '../model/modelAnimation';
 
 /**
  * The Default viewer is the default implementation of the AbstractViewer.
@@ -22,10 +23,6 @@ export class DefaultViewer extends AbstractViewer {
     constructor(public containerElement: HTMLElement, initialConfiguration: ViewerConfiguration = { extends: 'default' }) {
         super(containerElement, initialConfiguration);
         this.onModelLoadedObservable.add(this._onModelLoaded);
-        this.sceneManager.onSceneInitObservable.add(() => {
-            // extendClassWithConfig(this.sceneManager.scene, this._configuration.scene);
-            return this.sceneManager.scene;
-        });
 
         this.sceneManager.onLightsConfiguredObservable.add((data) => {
             this._configureLights(data.newConfiguration, data.model!);
@@ -55,48 +52,140 @@ export class DefaultViewer extends AbstractViewer {
     private _initNavbar() {
         let navbar = this.templateManager.getTemplate('navBar');
         if (navbar) {
-            let navbarHeight = navbar.parent.clientHeight + 'px';
-
-            let navbarShown: boolean = true;
-            let timeoutCancel /*: number*/;
-
-            let triggerNavbar = function (show: boolean = false, evt: PointerEvent) {
-                // only left-click on no-button.
-                if (!navbar || evt.button > 0) return;
-                // clear timeout
-                timeoutCancel && clearTimeout(timeoutCancel);
-                // if state is the same, do nothing
-                if (show === navbarShown) return;
-                //showing? simply show it!
-                if (show) {
-                    navbar.parent.style.bottom = show ? '0px' : '-' + navbarHeight;
-                    navbarShown = show;
+            this.onFrameRenderedObservable.add(this._updateProgressBar);
+            this.templateManager.eventManager.registerCallback('navBar', this._handlePointerDown, 'pointerdown');
+            // an example how to trigger the help button. publiclly available
+            this.templateManager.eventManager.registerCallback("navBar", () => {
+                // do your thing
+            }, "pointerdown", "#help-button");
+        }
+    }
+
+    private _animationList: string[];
+    private _currentAnimation: IModelAnimation;
+    private _isAnimationPaused: boolean;
+
+    private _handlePointerDown = (event: EventCallback) => {
+
+        let pointerDown = <PointerEvent>event.event;
+        if (pointerDown.button !== 0) return;
+        var element = (<HTMLElement>event.event.srcElement);
+
+        if (!element) {
+            return;
+        }
+
+        let parentClasses = element.parentElement!.classList;
+
+        switch (element.id) {
+            case "speed-button":
+            case "types-button":
+                if (parentClasses.contains("open")) {
+                    parentClasses.remove("open");
                 } else {
-                    let visibilityTimeout = 2000;
-                    if (navbar.configuration.params && navbar.configuration.params.visibilityTimeout !== undefined) {
-                        visibilityTimeout = <number>navbar.configuration.params.visibilityTimeout;
-                    }
-                    // not showing? set timeout until it is removed.
-                    timeoutCancel = setTimeout(function () {
-                        if (navbar) {
-                            navbar.parent.style.bottom = '-' + navbarHeight;
-                        }
-                        navbarShown = show;
-                    }, visibilityTimeout);
+                    parentClasses.add("open");
+                }
+                break;
+            case "play-pause-button":
+                this._togglePlayPause();
+                break;
+            case "label-option-button":
+                var label = element.dataset["value"];
+                if (label) {
+                    this._updateAnimationType(label);
                 }
+                break;
+            case "speed-option-button":
+                if (!this._currentAnimation) {
+                    return;
+                }
+                var speed = element.dataset["value"];
+                if (speed)
+                    this._updateAnimationSpeed(speed);
+                break;
+            case "progress-bar-container":
+                if (!this._currentAnimation) return;
+                const gotoFrame = (pointerDown.offsetX / element.clientWidth) * this._currentAnimation.frames;
+                if (isNaN(gotoFrame)) return;
+                this._currentAnimation.goToFrame(gotoFrame);
+                break;
+            case "fullscreen-button":
+                this.toggleFullscreen();
+            default:
+                return;
+        }
+    }
+
+    /**
+     * Plays or Pauses animation
+     */
+    private _togglePlayPause = () => {
+        if (!this._currentAnimation) {
+            return;
+        }
+        if (this._isAnimationPaused) {
+            this._currentAnimation.restart();
+        } else {
+            this._currentAnimation.pause();
+        }
+
+        this._isAnimationPaused = !this._isAnimationPaused;
+
+        let navbar = this.templateManager.getTemplate('navBar');
+        if (!navbar) return;
+
+        navbar.updateParams({
+            paused: this._isAnimationPaused,
+        });
+    }
+
+    /**
+     * Control progress bar position based on animation current frame
+     */
+    private _updateProgressBar = () => {
+        var progressWrapper = document.getElementById("progress-wrapper");
+        if (progressWrapper && this._currentAnimation) {
+            const progress = this._currentAnimation.currentFrame / this._currentAnimation.frames * 100;
+            if (isNaN(progress)) return;
+            progressWrapper.style.transform = "translateX(" + progress + "%)";
+        }
+    }
+
+    /** 
+     * Update Current Animation Speed
+     */
+    private _updateAnimationSpeed = (speed: string) => {
+        let navbar = this.templateManager.getTemplate('navBar');
+        if (!navbar) return;
+
+        if (speed && this._currentAnimation) {
+            this._currentAnimation.speedRatio = parseFloat(speed);
+            if (!this._isAnimationPaused) {
+                this._currentAnimation.restart();
             }
+            navbar.updateParams({
+                selectedSpeed: speed + "x",
+            });
+        }
+    }
 
-            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');
+    /** 
+     * Update Current Animation Type
+     */
+    private _updateAnimationType = (label: string) => {
+        let navbar = this.templateManager.getTemplate('navBar');
+        if (!navbar) return;
 
-            this.templateManager.eventManager.registerCallback('navBar', this.toggleFullscreen, 'pointerdown', '#fullscreen-button');
-            this.templateManager.eventManager.registerCallback('navBar', (data) => {
-                if (data && data.event && data.event.target)
-                    this.sceneManager.models[0].playAnimation(data.event.target['value']);
-            }, 'change', '#animation-selector');
+        if (label) {
+            this._currentAnimation = this.sceneManager.models[0].setCurrentAnimationByName(label);
         }
+
+        navbar.updateParams({
+            selectedAnimation: (this._animationList.indexOf(label) + 1),
+        });
+
+        // reset speed when a new animation is selected
+        this._updateAnimationSpeed("1.0");
     }
 
     /**
@@ -135,32 +224,19 @@ export class DefaultViewer extends AbstractViewer {
         let navbar = this.templateManager.getTemplate('navBar');
         if (!navbar) return;
 
-        if (model.getAnimationNames().length > 1) {
-            navbar.updateParams({ animations: model.getAnimationNames() });
+        if (model.getAnimationNames().length >= 1) {
+            this._isAnimationPaused = (model.configuration.animation && !model.configuration.animation.autoStart) || !model.configuration.animation;
+            this._animationList = model.getAnimationNames(),
+                navbar.updateParams({
+                    animations: this._animationList,
+                    paused: this._isAnimationPaused,
+                });
+
+            // default animation & speed
+            this._updateAnimationSpeed("1.0");
+            this._updateAnimationType(this._animationList[0]);
         }
-
         let modelConfiguration = model.configuration;
-
-        let metadataContainer = navbar.parent.querySelector('#model-metadata');
-        if (metadataContainer) {
-            if (modelConfiguration.title !== undefined) {
-                let element = metadataContainer.querySelector('span.model-title');
-                if (element) {
-                    element.innerHTML = modelConfiguration.title;
-                }
-            }
-
-            if (modelConfiguration.subtitle !== undefined) {
-                let element = metadataContainer.querySelector('span.model-subtitle');
-                if (element) {
-                    element.innerHTML = modelConfiguration.subtitle;
-                }
-            }
-
-            if (modelConfiguration.thumbnail !== undefined) {
-                (<HTMLDivElement>metadataContainer.querySelector('.thumbnail')).style.backgroundImage = `url('${modelConfiguration.thumbnail}')`;
-            }
-        }
     }
 
     /**
@@ -169,9 +245,12 @@ export class DefaultViewer extends AbstractViewer {
      * The scene will automatically be cleared of the old models, if exist.
      * @param model the configuration object (or URL) to load.
      */
-    public loadModel(model: any = this._configuration.model): Promise<ViewerModel> {
+    public loadModel(model?: string | IModelConfiguration): Promise<ViewerModel> {
+        if (!model) {
+            model = this.configuration.model;
+        }
         this.showLoadingScreen();
-        return super.loadModel(model, true).catch((error) => {
+        return super.loadModel(model!, true).catch((error) => {
             console.log(error);
             this.hideLoadingScreen();
             this.showOverlayScreen('error');
@@ -182,12 +261,14 @@ export class DefaultViewer extends AbstractViewer {
     private _onModelLoaded = (model: ViewerModel) => {
         this._configureTemplate(model);
         // with a short timeout, making sure everything is there already.
-        let hideLoadingDelay = 500;
+        let hideLoadingDelay = 20;
         if (this._configuration.lab && this._configuration.lab.hideLoadingDelay !== undefined) {
             hideLoadingDelay = this._configuration.lab.hideLoadingDelay;
         }
         setTimeout(() => {
-            this.hideLoadingScreen();
+            this.sceneManager.scene.executeWhenReady(() => {
+                this.hideLoadingScreen();
+            });
         }, hideLoadingDelay);
 
         return;

File diff suppressed because it is too large
+ 396 - 123
Viewer/src/viewer/sceneManager.ts


File diff suppressed because it is too large
+ 11 - 7
Viewer/src/viewer/viewer.ts


+ 4 - 4
Viewer/tests/unit/src/viewer/viewer.ts

@@ -76,7 +76,7 @@ describe('Viewer', function () {
         let viewer: DefaultViewer = <DefaultViewer>Helper.getNewViewerInstance();
         let renderCount = 0;
         let sceneRenderCount = 0;
-        viewer.onSceneInitObservable.add(() => {
+        viewer.onSceneInitObservable.add((scene) => {
             viewer.sceneManager.scene.registerBeforeRender(() => {
                 sceneRenderCount++;
             });
@@ -174,13 +174,13 @@ describe('Viewer', function () {
     it('should render in background if set to true', (done) => {
         let viewer = Helper.getNewViewerInstance();
         viewer.onInitDoneObservable.add(() => {
-            assert.isFalse(viewer.engine.renderEvenInBackground, "Engine is rendering in background");
+            assert.isTrue(viewer.engine.renderEvenInBackground, "Engine is rendering in background");
             viewer.updateConfiguration({
                 scene: {
-                    renderInBackground: true
+                    renderInBackground: false
                 }
             });
-            assert.isTrue(viewer.engine.renderEvenInBackground, "Engine is not rendering in background");
+            assert.isFalse(viewer.engine.renderEvenInBackground, "Engine is not rendering in background");
             viewer.dispose();
             done();
         });

+ 5 - 1
Viewer/tests/unit/webpack.config.js

@@ -42,8 +42,12 @@ module.exports = {
             }
         },
         {
-            test: /\.(jpe?g|png|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
+            test: /\.(jpe?g|png|ttf|eot|svg?)(\?[a-z0-9=&.]+)?$/,
             use: 'base64-image-loader?limit=1000&name=[name].[ext]'
+        },
+        {
+            test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
+            loader: 'base64-font-loader'
         }]
     },
     devServer: {

+ 5 - 1
Viewer/webpack.config.js

@@ -51,8 +51,12 @@ module.exports = {
             }
         },
         {
-            test: /\.(jpe?g|png|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
+            test: /\.(jpe?g|png|ttf|eot|svg?)(\?[a-z0-9=&.]+)?$/,
             use: 'base64-image-loader?limit=1000&name=[name].[ext]'
+        },
+        {
+            test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
+            loader: 'base64-font-loader'
         }]
     },
     devServer: {

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

@@ -47,8 +47,12 @@ module.exports = {
             }
         },
         {
-            test: /\.(jpe?g|png|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
+            test: /\.(jpe?g|png|ttf|eot|svg?)(\?[a-z0-9=&.]+)?$/,
             use: 'base64-image-loader?limit=1000&name=[name].[ext]'
+        },
+        {
+            test: /\.(woff|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
+            loader: 'base64-font-loader'
         }]
     }
 }

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


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


+ 87 - 98
dist/preview release/babylon.max.js

@@ -12017,7 +12017,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "3.2.0-rc.2";
+                return "3.2.0-rc.3";
             },
             enumerable: true,
             configurable: true
@@ -20386,7 +20386,6 @@ var BABYLON;
          */
         AbstractMesh.prototype.isCompletelyInFrustum = function (frustumPlanes) {
             return this._boundingInfo !== null && this._boundingInfo.isCompletelyInFrustum(frustumPlanes);
-            ;
         };
         /**
          * True if the mesh intersects another mesh or a SolidParticle object
@@ -29688,7 +29687,7 @@ var BABYLON;
                 case VertexBuffer.BYTE: {
                     var value = dataView.getInt8(byteOffset);
                     if (normalized) {
-                        value = (value + 0.5) / 127.5;
+                        value = Math.max(value / 127, -1);
                     }
                     return value;
                 }
@@ -29702,7 +29701,7 @@ var BABYLON;
                 case VertexBuffer.SHORT: {
                     var value = dataView.getInt16(byteOffset, true);
                     if (normalized) {
-                        value = (value + 0.5) / 16383.5;
+                        value = Math.max(value / 16383, -1);
                     }
                     return value;
                 }
@@ -35474,7 +35473,6 @@ var BABYLON;
             }
             var materialType = BABYLON.Tools.Instantiate(parsedMaterial.customType);
             return materialType.Parse(parsedMaterial, scene, rootUrl);
-            ;
         };
         // Triangle views
         Material._TriangleFillMode = 0;
@@ -38824,17 +38822,16 @@ var BABYLON;
             if (!data) {
                 return null;
             }
-            var defaultStride = BABYLON.VertexBuffer.DeduceStride(vertexBuffer.getKind());
-            var defaultByteStride = defaultStride * BABYLON.VertexBuffer.GetTypeByteLength(vertexBuffer.type);
-            var count = this._totalVertices * defaultStride;
-            if (vertexBuffer.type !== BABYLON.VertexBuffer.FLOAT || vertexBuffer.byteStride !== defaultByteStride) {
+            var tightlyPackedByteStride = vertexBuffer.getSize() * BABYLON.VertexBuffer.GetTypeByteLength(vertexBuffer.type);
+            var count = this._totalVertices * vertexBuffer.getSize();
+            if (vertexBuffer.type !== BABYLON.VertexBuffer.FLOAT || vertexBuffer.byteStride !== tightlyPackedByteStride) {
                 var copy_1 = new Array(count);
                 vertexBuffer.forEach(count, function (value, index) {
                     copy_1[index] = value;
                 });
                 return copy_1;
             }
-            if (!(data instanceof Array || data instanceof Float32Array) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
+            if (!((data instanceof Array) || (data instanceof Float32Array)) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
                 if (data instanceof Array) {
                     var offset = vertexBuffer.byteOffset / 4;
                     return BABYLON.Tools.Slice(data, offset, offset + count);
@@ -42922,23 +42919,6 @@ var BABYLON;
             };
             return _this;
         }
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
         Object.defineProperty(StandardMaterial.prototype, "imageProcessingConfiguration", {
             /**
              * Gets the image processing configuration used either in this material.
@@ -50084,7 +50064,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        ;
         Object.defineProperty(SpotLight.prototype, "projectionTextureLightNear", {
             /**
              * Gets the near clip of the Spotlight for texture projection.
@@ -51553,14 +51532,16 @@ var BABYLON;
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations or the smallest begin frame of all animations if null (defaults to 0)
+         * @param endFrame defines the new end frame for all animations or the largest end frame of all animations if null (defaults to null)
          */
         AnimationGroup.prototype.normalize = function (beginFrame, endFrame) {
-            if (beginFrame === void 0) { beginFrame = -Number.MAX_VALUE; }
-            if (endFrame === void 0) { endFrame = Number.MAX_VALUE; }
-            beginFrame = Math.max(beginFrame, this._from);
-            endFrame = Math.min(endFrame, this._to);
+            if (beginFrame === void 0) { beginFrame = 0; }
+            if (endFrame === void 0) { endFrame = null; }
+            if (beginFrame == null)
+                beginFrame = this._from;
+            if (endFrame == null)
+                endFrame = this._to;
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 var targetedAnimation = this._targetedAnimations[index];
                 var keys = targetedAnimation.animation.getKeys();
@@ -51587,6 +51568,8 @@ var BABYLON;
                     keys.push(newKey);
                 }
             }
+            this._from = beginFrame;
+            this._to = endFrame;
             return this;
         };
         /**
@@ -51882,8 +51865,13 @@ var BABYLON;
         });
         /**
          * Resets the runtime animation to the beginning
+         * @param restoreOriginal defines whether to restore the target property to the original value
          */
-        RuntimeAnimation.prototype.reset = function () {
+        RuntimeAnimation.prototype.reset = function (restoreOriginal) {
+            if (restoreOriginal === void 0) { restoreOriginal = false; }
+            if (restoreOriginal && this._originalValue != null) {
+                this.setValue(this._originalValue, -1);
+            }
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._currentFrame = 0;
@@ -51923,9 +51911,9 @@ var BABYLON;
             return this._animation._interpolate(currentFrame, repeatCount, this._workValue, loopMode, offsetValue, highLimitValue);
         };
         /**
-         * Affect the interpolated value to the target
+         * Apply the interpolated value to the target
          * @param currentValue defines the value computed by the animation
-         * @param weight defines the weight to apply to this value
+         * @param weight defines the weight to apply to this value (Defaults to 1.0)
          */
         RuntimeAnimation.prototype.setValue = function (currentValue, weight) {
             if (weight === void 0) { weight = 1.0; }
@@ -51939,14 +51927,7 @@ var BABYLON;
                 this._setValue(this._target, currentValue, weight);
             }
         };
-        /**
-         * Sets the value of the runtime animation
-         * @param target The target property of the runtime animation
-         * @param currentValue The current value to use for the runtime animation
-         * @param weight The weight to use for the runtime animation (Defaults to 1.0)
-         */
         RuntimeAnimation.prototype._setValue = function (target, currentValue, weight) {
-            if (weight === void 0) { weight = 1.0; }
             // Set value
             var path;
             var destination;
@@ -51966,9 +51947,23 @@ var BABYLON;
             this._targetPath = path;
             this._activeTarget = destination;
             this._weight = weight;
+            if (!this._originalValue) {
+                var originalValue = void 0;
+                if (destination.getRestPose && path === "_matrix") { // For bones
+                    originalValue = destination.getRestPose();
+                }
+                else {
+                    originalValue = destination[path];
+                }
+                if (originalValue && originalValue.clone) {
+                    this._originalValue = originalValue.clone();
+                }
+                else {
+                    this._originalValue = originalValue;
+                }
+            }
             // Blending
             var enableBlending = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;
-            var blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
             if (enableBlending && this._blendingFactor <= 1.0) {
                 if (!this._originalBlendValue) {
                     var originalValue = destination[path];
@@ -51979,25 +51974,6 @@ var BABYLON;
                         this._originalBlendValue = originalValue;
                     }
                 }
-            }
-            if (weight !== -1.0) {
-                if (!this._originalValue) {
-                    var originalValue = void 0;
-                    if (destination.getRestPose && path === "_matrix") { // For bones
-                        originalValue = destination.getRestPose();
-                    }
-                    else {
-                        originalValue = destination[path];
-                    }
-                    if (originalValue.clone) {
-                        this._originalValue = originalValue.clone();
-                    }
-                    else {
-                        this._originalValue = originalValue;
-                    }
-                }
-            }
-            if (enableBlending && this._blendingFactor <= 1.0) {
                 if (this._originalBlendValue.m) { // Matrix
                     if (BABYLON.Animation.AllowMatrixDecomposeForInterpolation) {
                         if (this._currentValue) {
@@ -52031,6 +52007,7 @@ var BABYLON;
                         this._currentValue = currentValue;
                     }
                 }
+                var blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
                 this._blendingFactor += blendingSpeed;
             }
             else {
@@ -52376,12 +52353,7 @@ var BABYLON;
         Animatable.prototype.reset = function () {
             var runtimeAnimations = this._runtimeAnimations;
             for (var index = 0; index < runtimeAnimations.length; index++) {
-                runtimeAnimations[index].reset();
-            }
-            // Reset to original value
-            for (index = 0; index < runtimeAnimations.length; index++) {
-                var animation = runtimeAnimations[index];
-                animation.animate(0, this.fromFrame, this.toFrame, false, this._speedRatio);
+                runtimeAnimations[index].reset(true);
             }
             this._localDelayOffset = null;
             this._pausedDelay = null;
@@ -56962,13 +56934,9 @@ var BABYLON;
             var serializationObject = {};
             serializationObject.type = this.getClassName();
             serializationObject.direction1 = this.direction1.asArray();
-            ;
             serializationObject.direction2 = this.direction2.asArray();
-            ;
             serializationObject.minEmitBox = this.minEmitBox.asArray();
-            ;
             serializationObject.maxEmitBox = this.maxEmitBox.asArray();
-            ;
             return serializationObject;
         };
         /**
@@ -57336,11 +57304,8 @@ var BABYLON;
          */
         SphereDirectedParticleEmitter.prototype.serialize = function () {
             var serializationObject = _super.prototype.serialize.call(this);
-            ;
             serializationObject.direction1 = this.direction1.asArray();
-            ;
             serializationObject.direction2 = this.direction2.asArray();
-            ;
             return serializationObject;
         };
         /**
@@ -58447,11 +58412,10 @@ var BABYLON;
             vertexData.indices = (this._depthSort) ? this._indices : this._indices32;
             vertexData.set(this._positions32, BABYLON.VertexBuffer.PositionKind);
             vertexData.set(this._normals32, BABYLON.VertexBuffer.NormalKind);
-            if (this._uvs32) {
+            if (this._uvs32.length > 0) {
                 vertexData.set(this._uvs32, BABYLON.VertexBuffer.UVKind);
-                ;
             }
-            if (this._colors32) {
+            if (this._colors32.length > 0) {
                 vertexData.set(this._colors32, BABYLON.VertexBuffer.ColorKind);
             }
             var mesh = new BABYLON.Mesh(this.name, this._scene);
@@ -61324,7 +61288,6 @@ var BABYLON;
             var step = pi2 / tessellation * arc;
             var rotated;
             var path = new Array();
-            ;
             for (i = 0; i <= tessellation; i++) {
                 var path = [];
                 if (cap == BABYLON.Mesh.CAP_START || cap == BABYLON.Mesh.CAP_ALL) {
@@ -64667,7 +64630,6 @@ var BABYLON;
             }
             if (y === null || y === undefined) {
                 var fontSize = parseInt((font.replace(/\D/g, '')));
-                ;
                 y = (size.height / 2) + (fontSize / 3.65);
             }
             this._context.fillStyle = color;
@@ -67413,7 +67375,7 @@ var BABYLON;
                     });
                 }, onProgress, function (scene, message, exception) {
                     reject(exception || new Error(message));
-                });
+                }, pluginExtension);
             });
         };
         /**
@@ -69305,8 +69267,8 @@ var BABYLON;
                     var transaction = this.db.transaction(["versions"]);
                     transaction.oncomplete = function (event) {
                         if (version) {
-                            // If the version in the JSON file is > than the version in DB
-                            if (_this.manifestVersionFound > version.data) {
+                            // If the version in the JSON file is different from the version in DB
+                            if (_this.manifestVersionFound !== version.data) {
                                 _this.mustUpdateRessources = true;
                                 updateInDBCallback();
                             }
@@ -86123,8 +86085,9 @@ var BABYLON;
          */
         function MorphTarget(
         /** defines the name of the target */
-        name, influence) {
+        name, influence, scene) {
             if (influence === void 0) { influence = 0; }
+            if (scene === void 0) { scene = null; }
             this.name = name;
             /**
              * Gets or sets the list of animations
@@ -86137,6 +86100,8 @@ var BABYLON;
              * Observable raised when the influence changes
              */
             this.onInfluenceChanged = new BABYLON.Observable();
+            this._animationPropertiesOverride = null;
+            this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this.influence = influence;
         }
         Object.defineProperty(MorphTarget.prototype, "influence", {
@@ -86159,6 +86124,22 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(MorphTarget.prototype, "animationPropertiesOverride", {
+            /**
+             * Gets or sets the animation properties override
+             */
+            get: function () {
+                if (!this._animationPropertiesOverride && this._scene) {
+                    return this._scene.animationPropertiesOverride;
+                }
+                return this._animationPropertiesOverride;
+            },
+            set: function (value) {
+                this._animationPropertiesOverride = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(MorphTarget.prototype, "hasPositions", {
             /**
              * Gets a boolean defining if the target contains position data
@@ -86285,7 +86266,7 @@ var BABYLON;
             if (!name) {
                 name = mesh.name;
             }
-            var result = new MorphTarget(name, influence);
+            var result = new MorphTarget(name, influence, mesh.getScene());
             result.setPositions(mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind));
             if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
                 result.setNormals(mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind));
@@ -87980,6 +87961,8 @@ var BABYLON;
             this._isActionableMesh = false;
             this._teleportationRequestInitiated = false;
             this._teleportationBackRequestInitiated = false;
+            this._rotationRightAsked = false;
+            this._rotationLeftAsked = false;
             this._dpadPressed = true;
             this._activePointer = false;
             this._id = VRExperienceHelperGazer._idCounter++;
@@ -88021,10 +88004,14 @@ var BABYLON;
             this._activePointer = false;
         };
         VRExperienceHelperGazer.prototype._updatePointerDistance = function (distance) {
+            if (distance === void 0) { distance = 100; }
         };
         VRExperienceHelperGazer.prototype.dispose = function () {
             this._interactionsEnabled = false;
             this._teleportationEnabled = false;
+            if (this._gazeTracker) {
+                this._gazeTracker.dispose();
+            }
         };
         VRExperienceHelperGazer._idCounter = 0;
         return VRExperienceHelperGazer;
@@ -88091,6 +88078,7 @@ var BABYLON;
             this._laserPointer.parent = mesh;
         };
         VRExperienceHelperControllerGazer.prototype._updatePointerDistance = function (distance) {
+            if (distance === void 0) { distance = 100; }
             this._laserPointer.scaling.y = distance;
             this._laserPointer.position.z = -distance / 2;
         };
@@ -88164,8 +88152,6 @@ var BABYLON;
             this._floorMeshesCollection = [];
             this._rotationAllowed = true;
             this._teleportBackwardsVector = new BABYLON.Vector3(0, -1, -1);
-            this._rotationRightAsked = false;
-            this._rotationLeftAsked = false;
             this._isDefaultTeleportationTarget = true;
             this._teleportationFillColor = "#444444";
             this._teleportationBorderColor = "#FFFFFF";
@@ -88599,7 +88585,7 @@ var BABYLON;
                     if (this.rightController) {
                         this.rightController._activatePointer();
                     }
-                    else if (this.leftController) {
+                    if (this.leftController) {
                         this.leftController._activatePointer();
                     }
                 }
@@ -89000,9 +88986,9 @@ var BABYLON;
             if (gazer._teleportationRequestInitiated) {
                 return;
             }
-            if (!this._rotationLeftAsked) {
+            if (!gazer._rotationLeftAsked) {
                 if (stateObject.x < -this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationLeftAsked = true;
+                    gazer._rotationLeftAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(false);
                     }
@@ -89010,12 +88996,12 @@ var BABYLON;
             }
             else {
                 if (stateObject.x > -this._padSensibilityDown) {
-                    this._rotationLeftAsked = false;
+                    gazer._rotationLeftAsked = false;
                 }
             }
-            if (!this._rotationRightAsked) {
+            if (!gazer._rotationRightAsked) {
                 if (stateObject.x > this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationRightAsked = true;
+                    gazer._rotationRightAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(true);
                     }
@@ -89023,7 +89009,7 @@ var BABYLON;
             }
             else {
                 if (stateObject.x < this._padSensibilityDown) {
-                    this._rotationRightAsked = false;
+                    gazer._rotationRightAsked = false;
                 }
             }
         };
@@ -89081,8 +89067,8 @@ var BABYLON;
                     controller.webVRController.onPadStateChangedObservable.add(function (stateObject) {
                         controller._dpadPressed = stateObject.pressed;
                         if (!controller._dpadPressed) {
-                            _this._rotationLeftAsked = false;
-                            _this._rotationRightAsked = false;
+                            controller._rotationLeftAsked = false;
+                            controller._rotationRightAsked = false;
                             controller._teleportationBackRequestInitiated = false;
                         }
                     });
@@ -89388,6 +89374,7 @@ var BABYLON;
                 gazer._updatePointerDistance(hit.distance);
             }
             else {
+                gazer._updatePointerDistance();
                 gazer._gazeTracker.isVisible = false;
             }
             if (hit && hit.pickedMesh) {
@@ -95929,6 +95916,8 @@ var BABYLON;
             }
             return false;
         };
+        NullEngine.prototype.releaseEffects = function () {
+        };
         return NullEngine;
     }(BABYLON.Engine));
     BABYLON.NullEngine = NullEngine;

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

@@ -11984,7 +11984,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "3.2.0-rc.2";
+                return "3.2.0-rc.3";
             },
             enumerable: true,
             configurable: true
@@ -20353,7 +20353,6 @@ var BABYLON;
          */
         AbstractMesh.prototype.isCompletelyInFrustum = function (frustumPlanes) {
             return this._boundingInfo !== null && this._boundingInfo.isCompletelyInFrustum(frustumPlanes);
-            ;
         };
         /**
          * True if the mesh intersects another mesh or a SolidParticle object
@@ -29655,7 +29654,7 @@ var BABYLON;
                 case VertexBuffer.BYTE: {
                     var value = dataView.getInt8(byteOffset);
                     if (normalized) {
-                        value = (value + 0.5) / 127.5;
+                        value = Math.max(value / 127, -1);
                     }
                     return value;
                 }
@@ -29669,7 +29668,7 @@ var BABYLON;
                 case VertexBuffer.SHORT: {
                     var value = dataView.getInt16(byteOffset, true);
                     if (normalized) {
-                        value = (value + 0.5) / 16383.5;
+                        value = Math.max(value / 16383, -1);
                     }
                     return value;
                 }
@@ -35441,7 +35440,6 @@ var BABYLON;
             }
             var materialType = BABYLON.Tools.Instantiate(parsedMaterial.customType);
             return materialType.Parse(parsedMaterial, scene, rootUrl);
-            ;
         };
         // Triangle views
         Material._TriangleFillMode = 0;
@@ -38791,17 +38789,16 @@ var BABYLON;
             if (!data) {
                 return null;
             }
-            var defaultStride = BABYLON.VertexBuffer.DeduceStride(vertexBuffer.getKind());
-            var defaultByteStride = defaultStride * BABYLON.VertexBuffer.GetTypeByteLength(vertexBuffer.type);
-            var count = this._totalVertices * defaultStride;
-            if (vertexBuffer.type !== BABYLON.VertexBuffer.FLOAT || vertexBuffer.byteStride !== defaultByteStride) {
+            var tightlyPackedByteStride = vertexBuffer.getSize() * BABYLON.VertexBuffer.GetTypeByteLength(vertexBuffer.type);
+            var count = this._totalVertices * vertexBuffer.getSize();
+            if (vertexBuffer.type !== BABYLON.VertexBuffer.FLOAT || vertexBuffer.byteStride !== tightlyPackedByteStride) {
                 var copy_1 = new Array(count);
                 vertexBuffer.forEach(count, function (value, index) {
                     copy_1[index] = value;
                 });
                 return copy_1;
             }
-            if (!(data instanceof Array || data instanceof Float32Array) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
+            if (!((data instanceof Array) || (data instanceof Float32Array)) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
                 if (data instanceof Array) {
                     var offset = vertexBuffer.byteOffset / 4;
                     return BABYLON.Tools.Slice(data, offset, offset + count);
@@ -42889,23 +42886,6 @@ var BABYLON;
             };
             return _this;
         }
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
         Object.defineProperty(StandardMaterial.prototype, "imageProcessingConfiguration", {
             /**
              * Gets the image processing configuration used either in this material.
@@ -50051,7 +50031,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        ;
         Object.defineProperty(SpotLight.prototype, "projectionTextureLightNear", {
             /**
              * Gets the near clip of the Spotlight for texture projection.
@@ -51520,14 +51499,16 @@ var BABYLON;
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations or the smallest begin frame of all animations if null (defaults to 0)
+         * @param endFrame defines the new end frame for all animations or the largest end frame of all animations if null (defaults to null)
          */
         AnimationGroup.prototype.normalize = function (beginFrame, endFrame) {
-            if (beginFrame === void 0) { beginFrame = -Number.MAX_VALUE; }
-            if (endFrame === void 0) { endFrame = Number.MAX_VALUE; }
-            beginFrame = Math.max(beginFrame, this._from);
-            endFrame = Math.min(endFrame, this._to);
+            if (beginFrame === void 0) { beginFrame = 0; }
+            if (endFrame === void 0) { endFrame = null; }
+            if (beginFrame == null)
+                beginFrame = this._from;
+            if (endFrame == null)
+                endFrame = this._to;
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 var targetedAnimation = this._targetedAnimations[index];
                 var keys = targetedAnimation.animation.getKeys();
@@ -51554,6 +51535,8 @@ var BABYLON;
                     keys.push(newKey);
                 }
             }
+            this._from = beginFrame;
+            this._to = endFrame;
             return this;
         };
         /**
@@ -51849,8 +51832,13 @@ var BABYLON;
         });
         /**
          * Resets the runtime animation to the beginning
+         * @param restoreOriginal defines whether to restore the target property to the original value
          */
-        RuntimeAnimation.prototype.reset = function () {
+        RuntimeAnimation.prototype.reset = function (restoreOriginal) {
+            if (restoreOriginal === void 0) { restoreOriginal = false; }
+            if (restoreOriginal && this._originalValue != null) {
+                this.setValue(this._originalValue, -1);
+            }
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._currentFrame = 0;
@@ -51890,9 +51878,9 @@ var BABYLON;
             return this._animation._interpolate(currentFrame, repeatCount, this._workValue, loopMode, offsetValue, highLimitValue);
         };
         /**
-         * Affect the interpolated value to the target
+         * Apply the interpolated value to the target
          * @param currentValue defines the value computed by the animation
-         * @param weight defines the weight to apply to this value
+         * @param weight defines the weight to apply to this value (Defaults to 1.0)
          */
         RuntimeAnimation.prototype.setValue = function (currentValue, weight) {
             if (weight === void 0) { weight = 1.0; }
@@ -51906,14 +51894,7 @@ var BABYLON;
                 this._setValue(this._target, currentValue, weight);
             }
         };
-        /**
-         * Sets the value of the runtime animation
-         * @param target The target property of the runtime animation
-         * @param currentValue The current value to use for the runtime animation
-         * @param weight The weight to use for the runtime animation (Defaults to 1.0)
-         */
         RuntimeAnimation.prototype._setValue = function (target, currentValue, weight) {
-            if (weight === void 0) { weight = 1.0; }
             // Set value
             var path;
             var destination;
@@ -51933,9 +51914,23 @@ var BABYLON;
             this._targetPath = path;
             this._activeTarget = destination;
             this._weight = weight;
+            if (!this._originalValue) {
+                var originalValue = void 0;
+                if (destination.getRestPose && path === "_matrix") { // For bones
+                    originalValue = destination.getRestPose();
+                }
+                else {
+                    originalValue = destination[path];
+                }
+                if (originalValue && originalValue.clone) {
+                    this._originalValue = originalValue.clone();
+                }
+                else {
+                    this._originalValue = originalValue;
+                }
+            }
             // Blending
             var enableBlending = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;
-            var blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
             if (enableBlending && this._blendingFactor <= 1.0) {
                 if (!this._originalBlendValue) {
                     var originalValue = destination[path];
@@ -51946,25 +51941,6 @@ var BABYLON;
                         this._originalBlendValue = originalValue;
                     }
                 }
-            }
-            if (weight !== -1.0) {
-                if (!this._originalValue) {
-                    var originalValue = void 0;
-                    if (destination.getRestPose && path === "_matrix") { // For bones
-                        originalValue = destination.getRestPose();
-                    }
-                    else {
-                        originalValue = destination[path];
-                    }
-                    if (originalValue.clone) {
-                        this._originalValue = originalValue.clone();
-                    }
-                    else {
-                        this._originalValue = originalValue;
-                    }
-                }
-            }
-            if (enableBlending && this._blendingFactor <= 1.0) {
                 if (this._originalBlendValue.m) { // Matrix
                     if (BABYLON.Animation.AllowMatrixDecomposeForInterpolation) {
                         if (this._currentValue) {
@@ -51998,6 +51974,7 @@ var BABYLON;
                         this._currentValue = currentValue;
                     }
                 }
+                var blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
                 this._blendingFactor += blendingSpeed;
             }
             else {
@@ -52343,12 +52320,7 @@ var BABYLON;
         Animatable.prototype.reset = function () {
             var runtimeAnimations = this._runtimeAnimations;
             for (var index = 0; index < runtimeAnimations.length; index++) {
-                runtimeAnimations[index].reset();
-            }
-            // Reset to original value
-            for (index = 0; index < runtimeAnimations.length; index++) {
-                var animation = runtimeAnimations[index];
-                animation.animate(0, this.fromFrame, this.toFrame, false, this._speedRatio);
+                runtimeAnimations[index].reset(true);
             }
             this._localDelayOffset = null;
             this._pausedDelay = null;
@@ -56929,13 +56901,9 @@ var BABYLON;
             var serializationObject = {};
             serializationObject.type = this.getClassName();
             serializationObject.direction1 = this.direction1.asArray();
-            ;
             serializationObject.direction2 = this.direction2.asArray();
-            ;
             serializationObject.minEmitBox = this.minEmitBox.asArray();
-            ;
             serializationObject.maxEmitBox = this.maxEmitBox.asArray();
-            ;
             return serializationObject;
         };
         /**
@@ -57303,11 +57271,8 @@ var BABYLON;
          */
         SphereDirectedParticleEmitter.prototype.serialize = function () {
             var serializationObject = _super.prototype.serialize.call(this);
-            ;
             serializationObject.direction1 = this.direction1.asArray();
-            ;
             serializationObject.direction2 = this.direction2.asArray();
-            ;
             return serializationObject;
         };
         /**
@@ -58414,11 +58379,10 @@ var BABYLON;
             vertexData.indices = (this._depthSort) ? this._indices : this._indices32;
             vertexData.set(this._positions32, BABYLON.VertexBuffer.PositionKind);
             vertexData.set(this._normals32, BABYLON.VertexBuffer.NormalKind);
-            if (this._uvs32) {
+            if (this._uvs32.length > 0) {
                 vertexData.set(this._uvs32, BABYLON.VertexBuffer.UVKind);
-                ;
             }
-            if (this._colors32) {
+            if (this._colors32.length > 0) {
                 vertexData.set(this._colors32, BABYLON.VertexBuffer.ColorKind);
             }
             var mesh = new BABYLON.Mesh(this.name, this._scene);
@@ -61291,7 +61255,6 @@ var BABYLON;
             var step = pi2 / tessellation * arc;
             var rotated;
             var path = new Array();
-            ;
             for (i = 0; i <= tessellation; i++) {
                 var path = [];
                 if (cap == BABYLON.Mesh.CAP_START || cap == BABYLON.Mesh.CAP_ALL) {
@@ -64634,7 +64597,6 @@ var BABYLON;
             }
             if (y === null || y === undefined) {
                 var fontSize = parseInt((font.replace(/\D/g, '')));
-                ;
                 y = (size.height / 2) + (fontSize / 3.65);
             }
             this._context.fillStyle = color;
@@ -67380,7 +67342,7 @@ var BABYLON;
                     });
                 }, onProgress, function (scene, message, exception) {
                     reject(exception || new Error(message));
-                });
+                }, pluginExtension);
             });
         };
         /**
@@ -69272,8 +69234,8 @@ var BABYLON;
                     var transaction = this.db.transaction(["versions"]);
                     transaction.oncomplete = function (event) {
                         if (version) {
-                            // If the version in the JSON file is > than the version in DB
-                            if (_this.manifestVersionFound > version.data) {
+                            // If the version in the JSON file is different from the version in DB
+                            if (_this.manifestVersionFound !== version.data) {
                                 _this.mustUpdateRessources = true;
                                 updateInDBCallback();
                             }
@@ -86090,8 +86052,9 @@ var BABYLON;
          */
         function MorphTarget(
         /** defines the name of the target */
-        name, influence) {
+        name, influence, scene) {
             if (influence === void 0) { influence = 0; }
+            if (scene === void 0) { scene = null; }
             this.name = name;
             /**
              * Gets or sets the list of animations
@@ -86104,6 +86067,8 @@ var BABYLON;
              * Observable raised when the influence changes
              */
             this.onInfluenceChanged = new BABYLON.Observable();
+            this._animationPropertiesOverride = null;
+            this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this.influence = influence;
         }
         Object.defineProperty(MorphTarget.prototype, "influence", {
@@ -86126,6 +86091,22 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(MorphTarget.prototype, "animationPropertiesOverride", {
+            /**
+             * Gets or sets the animation properties override
+             */
+            get: function () {
+                if (!this._animationPropertiesOverride && this._scene) {
+                    return this._scene.animationPropertiesOverride;
+                }
+                return this._animationPropertiesOverride;
+            },
+            set: function (value) {
+                this._animationPropertiesOverride = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(MorphTarget.prototype, "hasPositions", {
             /**
              * Gets a boolean defining if the target contains position data
@@ -86252,7 +86233,7 @@ var BABYLON;
             if (!name) {
                 name = mesh.name;
             }
-            var result = new MorphTarget(name, influence);
+            var result = new MorphTarget(name, influence, mesh.getScene());
             result.setPositions(mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind));
             if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
                 result.setNormals(mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind));
@@ -87947,6 +87928,8 @@ var BABYLON;
             this._isActionableMesh = false;
             this._teleportationRequestInitiated = false;
             this._teleportationBackRequestInitiated = false;
+            this._rotationRightAsked = false;
+            this._rotationLeftAsked = false;
             this._dpadPressed = true;
             this._activePointer = false;
             this._id = VRExperienceHelperGazer._idCounter++;
@@ -87988,10 +87971,14 @@ var BABYLON;
             this._activePointer = false;
         };
         VRExperienceHelperGazer.prototype._updatePointerDistance = function (distance) {
+            if (distance === void 0) { distance = 100; }
         };
         VRExperienceHelperGazer.prototype.dispose = function () {
             this._interactionsEnabled = false;
             this._teleportationEnabled = false;
+            if (this._gazeTracker) {
+                this._gazeTracker.dispose();
+            }
         };
         VRExperienceHelperGazer._idCounter = 0;
         return VRExperienceHelperGazer;
@@ -88058,6 +88045,7 @@ var BABYLON;
             this._laserPointer.parent = mesh;
         };
         VRExperienceHelperControllerGazer.prototype._updatePointerDistance = function (distance) {
+            if (distance === void 0) { distance = 100; }
             this._laserPointer.scaling.y = distance;
             this._laserPointer.position.z = -distance / 2;
         };
@@ -88131,8 +88119,6 @@ var BABYLON;
             this._floorMeshesCollection = [];
             this._rotationAllowed = true;
             this._teleportBackwardsVector = new BABYLON.Vector3(0, -1, -1);
-            this._rotationRightAsked = false;
-            this._rotationLeftAsked = false;
             this._isDefaultTeleportationTarget = true;
             this._teleportationFillColor = "#444444";
             this._teleportationBorderColor = "#FFFFFF";
@@ -88566,7 +88552,7 @@ var BABYLON;
                     if (this.rightController) {
                         this.rightController._activatePointer();
                     }
-                    else if (this.leftController) {
+                    if (this.leftController) {
                         this.leftController._activatePointer();
                     }
                 }
@@ -88967,9 +88953,9 @@ var BABYLON;
             if (gazer._teleportationRequestInitiated) {
                 return;
             }
-            if (!this._rotationLeftAsked) {
+            if (!gazer._rotationLeftAsked) {
                 if (stateObject.x < -this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationLeftAsked = true;
+                    gazer._rotationLeftAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(false);
                     }
@@ -88977,12 +88963,12 @@ var BABYLON;
             }
             else {
                 if (stateObject.x > -this._padSensibilityDown) {
-                    this._rotationLeftAsked = false;
+                    gazer._rotationLeftAsked = false;
                 }
             }
-            if (!this._rotationRightAsked) {
+            if (!gazer._rotationRightAsked) {
                 if (stateObject.x > this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationRightAsked = true;
+                    gazer._rotationRightAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(true);
                     }
@@ -88990,7 +88976,7 @@ var BABYLON;
             }
             else {
                 if (stateObject.x < this._padSensibilityDown) {
-                    this._rotationRightAsked = false;
+                    gazer._rotationRightAsked = false;
                 }
             }
         };
@@ -89048,8 +89034,8 @@ var BABYLON;
                     controller.webVRController.onPadStateChangedObservable.add(function (stateObject) {
                         controller._dpadPressed = stateObject.pressed;
                         if (!controller._dpadPressed) {
-                            _this._rotationLeftAsked = false;
-                            _this._rotationRightAsked = false;
+                            controller._rotationLeftAsked = false;
+                            controller._rotationRightAsked = false;
                             controller._teleportationBackRequestInitiated = false;
                         }
                     });
@@ -89355,6 +89341,7 @@ var BABYLON;
                 gazer._updatePointerDistance(hit.distance);
             }
             else {
+                gazer._updatePointerDistance();
                 gazer._gazeTracker.isVisible = false;
             }
             if (hit && hit.pickedMesh) {
@@ -95896,6 +95883,8 @@ var BABYLON;
             }
             return false;
         };
+        NullEngine.prototype.releaseEffects = function () {
+        };
         return NullEngine;
     }(BABYLON.Engine));
     BABYLON.NullEngine = NullEngine;

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


+ 87 - 98
dist/preview release/es6.js

@@ -11984,7 +11984,7 @@ var BABYLON;
              * Returns the current version of the framework
              */
             get: function () {
-                return "3.2.0-rc.2";
+                return "3.2.0-rc.3";
             },
             enumerable: true,
             configurable: true
@@ -20353,7 +20353,6 @@ var BABYLON;
          */
         AbstractMesh.prototype.isCompletelyInFrustum = function (frustumPlanes) {
             return this._boundingInfo !== null && this._boundingInfo.isCompletelyInFrustum(frustumPlanes);
-            ;
         };
         /**
          * True if the mesh intersects another mesh or a SolidParticle object
@@ -29655,7 +29654,7 @@ var BABYLON;
                 case VertexBuffer.BYTE: {
                     var value = dataView.getInt8(byteOffset);
                     if (normalized) {
-                        value = (value + 0.5) / 127.5;
+                        value = Math.max(value / 127, -1);
                     }
                     return value;
                 }
@@ -29669,7 +29668,7 @@ var BABYLON;
                 case VertexBuffer.SHORT: {
                     var value = dataView.getInt16(byteOffset, true);
                     if (normalized) {
-                        value = (value + 0.5) / 16383.5;
+                        value = Math.max(value / 16383, -1);
                     }
                     return value;
                 }
@@ -35441,7 +35440,6 @@ var BABYLON;
             }
             var materialType = BABYLON.Tools.Instantiate(parsedMaterial.customType);
             return materialType.Parse(parsedMaterial, scene, rootUrl);
-            ;
         };
         // Triangle views
         Material._TriangleFillMode = 0;
@@ -38791,17 +38789,16 @@ var BABYLON;
             if (!data) {
                 return null;
             }
-            var defaultStride = BABYLON.VertexBuffer.DeduceStride(vertexBuffer.getKind());
-            var defaultByteStride = defaultStride * BABYLON.VertexBuffer.GetTypeByteLength(vertexBuffer.type);
-            var count = this._totalVertices * defaultStride;
-            if (vertexBuffer.type !== BABYLON.VertexBuffer.FLOAT || vertexBuffer.byteStride !== defaultByteStride) {
+            var tightlyPackedByteStride = vertexBuffer.getSize() * BABYLON.VertexBuffer.GetTypeByteLength(vertexBuffer.type);
+            var count = this._totalVertices * vertexBuffer.getSize();
+            if (vertexBuffer.type !== BABYLON.VertexBuffer.FLOAT || vertexBuffer.byteStride !== tightlyPackedByteStride) {
                 var copy_1 = new Array(count);
                 vertexBuffer.forEach(count, function (value, index) {
                     copy_1[index] = value;
                 });
                 return copy_1;
             }
-            if (!(data instanceof Array || data instanceof Float32Array) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
+            if (!((data instanceof Array) || (data instanceof Float32Array)) || vertexBuffer.byteOffset !== 0 || data.length !== count) {
                 if (data instanceof Array) {
                     var offset = vertexBuffer.byteOffset / 4;
                     return BABYLON.Tools.Slice(data, offset, offset + count);
@@ -42889,23 +42886,6 @@ var BABYLON;
             };
             return _this;
         }
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
-        ;
         Object.defineProperty(StandardMaterial.prototype, "imageProcessingConfiguration", {
             /**
              * Gets the image processing configuration used either in this material.
@@ -50051,7 +50031,6 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
-        ;
         Object.defineProperty(SpotLight.prototype, "projectionTextureLightNear", {
             /**
              * Gets the near clip of the Spotlight for texture projection.
@@ -51520,14 +51499,16 @@ var BABYLON;
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations or the smallest begin frame of all animations if null (defaults to 0)
+         * @param endFrame defines the new end frame for all animations or the largest end frame of all animations if null (defaults to null)
          */
         AnimationGroup.prototype.normalize = function (beginFrame, endFrame) {
-            if (beginFrame === void 0) { beginFrame = -Number.MAX_VALUE; }
-            if (endFrame === void 0) { endFrame = Number.MAX_VALUE; }
-            beginFrame = Math.max(beginFrame, this._from);
-            endFrame = Math.min(endFrame, this._to);
+            if (beginFrame === void 0) { beginFrame = 0; }
+            if (endFrame === void 0) { endFrame = null; }
+            if (beginFrame == null)
+                beginFrame = this._from;
+            if (endFrame == null)
+                endFrame = this._to;
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 var targetedAnimation = this._targetedAnimations[index];
                 var keys = targetedAnimation.animation.getKeys();
@@ -51554,6 +51535,8 @@ var BABYLON;
                     keys.push(newKey);
                 }
             }
+            this._from = beginFrame;
+            this._to = endFrame;
             return this;
         };
         /**
@@ -51849,8 +51832,13 @@ var BABYLON;
         });
         /**
          * Resets the runtime animation to the beginning
+         * @param restoreOriginal defines whether to restore the target property to the original value
          */
-        RuntimeAnimation.prototype.reset = function () {
+        RuntimeAnimation.prototype.reset = function (restoreOriginal) {
+            if (restoreOriginal === void 0) { restoreOriginal = false; }
+            if (restoreOriginal && this._originalValue != null) {
+                this.setValue(this._originalValue, -1);
+            }
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._currentFrame = 0;
@@ -51890,9 +51878,9 @@ var BABYLON;
             return this._animation._interpolate(currentFrame, repeatCount, this._workValue, loopMode, offsetValue, highLimitValue);
         };
         /**
-         * Affect the interpolated value to the target
+         * Apply the interpolated value to the target
          * @param currentValue defines the value computed by the animation
-         * @param weight defines the weight to apply to this value
+         * @param weight defines the weight to apply to this value (Defaults to 1.0)
          */
         RuntimeAnimation.prototype.setValue = function (currentValue, weight) {
             if (weight === void 0) { weight = 1.0; }
@@ -51906,14 +51894,7 @@ var BABYLON;
                 this._setValue(this._target, currentValue, weight);
             }
         };
-        /**
-         * Sets the value of the runtime animation
-         * @param target The target property of the runtime animation
-         * @param currentValue The current value to use for the runtime animation
-         * @param weight The weight to use for the runtime animation (Defaults to 1.0)
-         */
         RuntimeAnimation.prototype._setValue = function (target, currentValue, weight) {
-            if (weight === void 0) { weight = 1.0; }
             // Set value
             var path;
             var destination;
@@ -51933,9 +51914,23 @@ var BABYLON;
             this._targetPath = path;
             this._activeTarget = destination;
             this._weight = weight;
+            if (!this._originalValue) {
+                var originalValue = void 0;
+                if (destination.getRestPose && path === "_matrix") { // For bones
+                    originalValue = destination.getRestPose();
+                }
+                else {
+                    originalValue = destination[path];
+                }
+                if (originalValue && originalValue.clone) {
+                    this._originalValue = originalValue.clone();
+                }
+                else {
+                    this._originalValue = originalValue;
+                }
+            }
             // Blending
             var enableBlending = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;
-            var blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
             if (enableBlending && this._blendingFactor <= 1.0) {
                 if (!this._originalBlendValue) {
                     var originalValue = destination[path];
@@ -51946,25 +51941,6 @@ var BABYLON;
                         this._originalBlendValue = originalValue;
                     }
                 }
-            }
-            if (weight !== -1.0) {
-                if (!this._originalValue) {
-                    var originalValue = void 0;
-                    if (destination.getRestPose && path === "_matrix") { // For bones
-                        originalValue = destination.getRestPose();
-                    }
-                    else {
-                        originalValue = destination[path];
-                    }
-                    if (originalValue.clone) {
-                        this._originalValue = originalValue.clone();
-                    }
-                    else {
-                        this._originalValue = originalValue;
-                    }
-                }
-            }
-            if (enableBlending && this._blendingFactor <= 1.0) {
                 if (this._originalBlendValue.m) { // Matrix
                     if (BABYLON.Animation.AllowMatrixDecomposeForInterpolation) {
                         if (this._currentValue) {
@@ -51998,6 +51974,7 @@ var BABYLON;
                         this._currentValue = currentValue;
                     }
                 }
+                var blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
                 this._blendingFactor += blendingSpeed;
             }
             else {
@@ -52343,12 +52320,7 @@ var BABYLON;
         Animatable.prototype.reset = function () {
             var runtimeAnimations = this._runtimeAnimations;
             for (var index = 0; index < runtimeAnimations.length; index++) {
-                runtimeAnimations[index].reset();
-            }
-            // Reset to original value
-            for (index = 0; index < runtimeAnimations.length; index++) {
-                var animation = runtimeAnimations[index];
-                animation.animate(0, this.fromFrame, this.toFrame, false, this._speedRatio);
+                runtimeAnimations[index].reset(true);
             }
             this._localDelayOffset = null;
             this._pausedDelay = null;
@@ -56929,13 +56901,9 @@ var BABYLON;
             var serializationObject = {};
             serializationObject.type = this.getClassName();
             serializationObject.direction1 = this.direction1.asArray();
-            ;
             serializationObject.direction2 = this.direction2.asArray();
-            ;
             serializationObject.minEmitBox = this.minEmitBox.asArray();
-            ;
             serializationObject.maxEmitBox = this.maxEmitBox.asArray();
-            ;
             return serializationObject;
         };
         /**
@@ -57303,11 +57271,8 @@ var BABYLON;
          */
         SphereDirectedParticleEmitter.prototype.serialize = function () {
             var serializationObject = _super.prototype.serialize.call(this);
-            ;
             serializationObject.direction1 = this.direction1.asArray();
-            ;
             serializationObject.direction2 = this.direction2.asArray();
-            ;
             return serializationObject;
         };
         /**
@@ -58414,11 +58379,10 @@ var BABYLON;
             vertexData.indices = (this._depthSort) ? this._indices : this._indices32;
             vertexData.set(this._positions32, BABYLON.VertexBuffer.PositionKind);
             vertexData.set(this._normals32, BABYLON.VertexBuffer.NormalKind);
-            if (this._uvs32) {
+            if (this._uvs32.length > 0) {
                 vertexData.set(this._uvs32, BABYLON.VertexBuffer.UVKind);
-                ;
             }
-            if (this._colors32) {
+            if (this._colors32.length > 0) {
                 vertexData.set(this._colors32, BABYLON.VertexBuffer.ColorKind);
             }
             var mesh = new BABYLON.Mesh(this.name, this._scene);
@@ -61291,7 +61255,6 @@ var BABYLON;
             var step = pi2 / tessellation * arc;
             var rotated;
             var path = new Array();
-            ;
             for (i = 0; i <= tessellation; i++) {
                 var path = [];
                 if (cap == BABYLON.Mesh.CAP_START || cap == BABYLON.Mesh.CAP_ALL) {
@@ -64634,7 +64597,6 @@ var BABYLON;
             }
             if (y === null || y === undefined) {
                 var fontSize = parseInt((font.replace(/\D/g, '')));
-                ;
                 y = (size.height / 2) + (fontSize / 3.65);
             }
             this._context.fillStyle = color;
@@ -67380,7 +67342,7 @@ var BABYLON;
                     });
                 }, onProgress, function (scene, message, exception) {
                     reject(exception || new Error(message));
-                });
+                }, pluginExtension);
             });
         };
         /**
@@ -69272,8 +69234,8 @@ var BABYLON;
                     var transaction = this.db.transaction(["versions"]);
                     transaction.oncomplete = function (event) {
                         if (version) {
-                            // If the version in the JSON file is > than the version in DB
-                            if (_this.manifestVersionFound > version.data) {
+                            // If the version in the JSON file is different from the version in DB
+                            if (_this.manifestVersionFound !== version.data) {
                                 _this.mustUpdateRessources = true;
                                 updateInDBCallback();
                             }
@@ -86090,8 +86052,9 @@ var BABYLON;
          */
         function MorphTarget(
         /** defines the name of the target */
-        name, influence) {
+        name, influence, scene) {
             if (influence === void 0) { influence = 0; }
+            if (scene === void 0) { scene = null; }
             this.name = name;
             /**
              * Gets or sets the list of animations
@@ -86104,6 +86067,8 @@ var BABYLON;
              * Observable raised when the influence changes
              */
             this.onInfluenceChanged = new BABYLON.Observable();
+            this._animationPropertiesOverride = null;
+            this._scene = scene || BABYLON.Engine.LastCreatedScene;
             this.influence = influence;
         }
         Object.defineProperty(MorphTarget.prototype, "influence", {
@@ -86126,6 +86091,22 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(MorphTarget.prototype, "animationPropertiesOverride", {
+            /**
+             * Gets or sets the animation properties override
+             */
+            get: function () {
+                if (!this._animationPropertiesOverride && this._scene) {
+                    return this._scene.animationPropertiesOverride;
+                }
+                return this._animationPropertiesOverride;
+            },
+            set: function (value) {
+                this._animationPropertiesOverride = value;
+            },
+            enumerable: true,
+            configurable: true
+        });
         Object.defineProperty(MorphTarget.prototype, "hasPositions", {
             /**
              * Gets a boolean defining if the target contains position data
@@ -86252,7 +86233,7 @@ var BABYLON;
             if (!name) {
                 name = mesh.name;
             }
-            var result = new MorphTarget(name, influence);
+            var result = new MorphTarget(name, influence, mesh.getScene());
             result.setPositions(mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind));
             if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
                 result.setNormals(mesh.getVerticesData(BABYLON.VertexBuffer.NormalKind));
@@ -87947,6 +87928,8 @@ var BABYLON;
             this._isActionableMesh = false;
             this._teleportationRequestInitiated = false;
             this._teleportationBackRequestInitiated = false;
+            this._rotationRightAsked = false;
+            this._rotationLeftAsked = false;
             this._dpadPressed = true;
             this._activePointer = false;
             this._id = VRExperienceHelperGazer._idCounter++;
@@ -87988,10 +87971,14 @@ var BABYLON;
             this._activePointer = false;
         };
         VRExperienceHelperGazer.prototype._updatePointerDistance = function (distance) {
+            if (distance === void 0) { distance = 100; }
         };
         VRExperienceHelperGazer.prototype.dispose = function () {
             this._interactionsEnabled = false;
             this._teleportationEnabled = false;
+            if (this._gazeTracker) {
+                this._gazeTracker.dispose();
+            }
         };
         VRExperienceHelperGazer._idCounter = 0;
         return VRExperienceHelperGazer;
@@ -88058,6 +88045,7 @@ var BABYLON;
             this._laserPointer.parent = mesh;
         };
         VRExperienceHelperControllerGazer.prototype._updatePointerDistance = function (distance) {
+            if (distance === void 0) { distance = 100; }
             this._laserPointer.scaling.y = distance;
             this._laserPointer.position.z = -distance / 2;
         };
@@ -88131,8 +88119,6 @@ var BABYLON;
             this._floorMeshesCollection = [];
             this._rotationAllowed = true;
             this._teleportBackwardsVector = new BABYLON.Vector3(0, -1, -1);
-            this._rotationRightAsked = false;
-            this._rotationLeftAsked = false;
             this._isDefaultTeleportationTarget = true;
             this._teleportationFillColor = "#444444";
             this._teleportationBorderColor = "#FFFFFF";
@@ -88566,7 +88552,7 @@ var BABYLON;
                     if (this.rightController) {
                         this.rightController._activatePointer();
                     }
-                    else if (this.leftController) {
+                    if (this.leftController) {
                         this.leftController._activatePointer();
                     }
                 }
@@ -88967,9 +88953,9 @@ var BABYLON;
             if (gazer._teleportationRequestInitiated) {
                 return;
             }
-            if (!this._rotationLeftAsked) {
+            if (!gazer._rotationLeftAsked) {
                 if (stateObject.x < -this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationLeftAsked = true;
+                    gazer._rotationLeftAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(false);
                     }
@@ -88977,12 +88963,12 @@ var BABYLON;
             }
             else {
                 if (stateObject.x > -this._padSensibilityDown) {
-                    this._rotationLeftAsked = false;
+                    gazer._rotationLeftAsked = false;
                 }
             }
-            if (!this._rotationRightAsked) {
+            if (!gazer._rotationRightAsked) {
                 if (stateObject.x > this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationRightAsked = true;
+                    gazer._rotationRightAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(true);
                     }
@@ -88990,7 +88976,7 @@ var BABYLON;
             }
             else {
                 if (stateObject.x < this._padSensibilityDown) {
-                    this._rotationRightAsked = false;
+                    gazer._rotationRightAsked = false;
                 }
             }
         };
@@ -89048,8 +89034,8 @@ var BABYLON;
                     controller.webVRController.onPadStateChangedObservable.add(function (stateObject) {
                         controller._dpadPressed = stateObject.pressed;
                         if (!controller._dpadPressed) {
-                            _this._rotationLeftAsked = false;
-                            _this._rotationRightAsked = false;
+                            controller._rotationLeftAsked = false;
+                            controller._rotationRightAsked = false;
                             controller._teleportationBackRequestInitiated = false;
                         }
                     });
@@ -89355,6 +89341,7 @@ var BABYLON;
                 gazer._updatePointerDistance(hit.distance);
             }
             else {
+                gazer._updatePointerDistance();
                 gazer._gazeTracker.isVisible = false;
             }
             if (hit && hit.pickedMesh) {
@@ -95896,6 +95883,8 @@ var BABYLON;
             }
             return false;
         };
+        NullEngine.prototype.releaseEffects = function () {
+        };
         return NullEngine;
     }(BABYLON.Engine));
     BABYLON.NullEngine = NullEngine;

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

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "3.2.0-rc.2",
+    "version": "3.2.0-rc.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

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

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

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


+ 6 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -226,6 +226,12 @@ declare module INSPECTOR {
         'PhysicsImpostor': {
             type: typeof BABYLON.PhysicsImpostor;
         };
+        'ImageProcessingConfiguration': {
+            type: typeof BABYLON.ImageProcessingConfiguration;
+        };
+        'ColorCurves': {
+            type: typeof BABYLON.ColorCurves;
+        };
     };
 }
 

+ 6 - 0
dist/preview release/inspector/babylon.inspector.js

@@ -477,6 +477,12 @@ var INSPECTOR;
         'PhysicsImpostor': {
             type: BABYLON.PhysicsImpostor
         },
+        'ImageProcessingConfiguration': {
+            type: BABYLON.ImageProcessingConfiguration
+        },
+        'ColorCurves': {
+            type: BABYLON.ColorCurves
+        }
     };
 })(INSPECTOR || (INSPECTOR = {}));
 

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


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

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

+ 2 - 4
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -406,15 +406,13 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onCameraLoadedObservable.add(function (camera) { return _this.onCameraLoadedObservable.notifyObservers(camera); });
-            loader.onExtensionLoadedObservable.add(function (extension) {
-                _this.onExtensionLoadedObservable.notifyObservers(extension);
-                _this.onExtensionLoadedObservable.clear();
-            });
+            loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();
                 _this.onMaterialLoadedObservable.clear();
                 _this.onCameraLoadedObservable.clear();
+                _this.onExtensionLoadedObservable.clear();
                 _this.onCompleteObservable.notifyObservers(_this);
                 _this.onCompleteObservable.clear();
             });

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


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

@@ -443,7 +443,7 @@ declare module BABYLON.GLTF2 {
         _parent: _ILoaderNode;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
-        _babylonAnimationTargets?: Node[];
+        _babylonBones?: Bone[];
         _numMorphTargets?: number;
     }
     /** @hidden */

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

@@ -406,15 +406,13 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onCameraLoadedObservable.add(function (camera) { return _this.onCameraLoadedObservable.notifyObservers(camera); });
-            loader.onExtensionLoadedObservable.add(function (extension) {
-                _this.onExtensionLoadedObservable.notifyObservers(extension);
-                _this.onExtensionLoadedObservable.clear();
-            });
+            loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();
                 _this.onMaterialLoadedObservable.clear();
                 _this.onCameraLoadedObservable.clear();
+                _this.onExtensionLoadedObservable.clear();
                 _this.onCompleteObservable.notifyObservers(_this);
                 _this.onCompleteObservable.clear();
             });
@@ -1055,8 +1053,6 @@ var BABYLON;
                 var promises = new Array();
                 var babylonMesh = new BABYLON.Mesh(node.name || "node" + node._index, this._babylonScene, node._parent._babylonMesh);
                 node._babylonMesh = babylonMesh;
-                node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-                node._babylonAnimationTargets.push(babylonMesh);
                 GLTFLoader._LoadTransform(node, babylonMesh);
                 if (node.mesh != undefined) {
                     var mesh = GLTFLoader._GetProperty(context + "/mesh", this._gltf.meshes, node.mesh);
@@ -1320,8 +1316,8 @@ var BABYLON;
                 var boneIndex = skin.joints.indexOf(node._index);
                 babylonBone = new BABYLON.Bone(node.name || "joint" + node._index, skin._babylonSkeleton, babylonParentBone, this._getNodeMatrix(node), null, null, boneIndex);
                 babylonBones[node._index] = babylonBone;
-                node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-                node._babylonAnimationTargets.push(babylonBone);
+                node._babylonBones = node._babylonBones || [];
+                node._babylonBones.push(babylonBone);
                 return babylonBone;
             };
             GLTFLoader.prototype._loadSkinInverseBindMatricesDataAsync = function (context, skin) {
@@ -1418,7 +1414,7 @@ var BABYLON;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
                 // Ignore animations that have no animation targets.
                 if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||
-                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonAnimationTargets)) {
+                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonMesh)) {
                     return Promise.resolve();
                 }
                 // Ignore animations targeting TRS of skinned nodes.
@@ -1534,13 +1530,12 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            var morphTargets = new Array();
                             _this._forEachPrimitive(targetNode, function (babylonMesh) {
                                 var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
-                                morphTarget.animations.push(babylonAnimation);
-                                morphTargets.push(morphTarget);
+                                var babylonAnimationClone = babylonAnimation.clone();
+                                morphTarget.animations.push(babylonAnimationClone);
+                                babylonAnimationGroup.addTargetedAnimation(babylonAnimationClone, morphTarget);
                             });
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTargets);
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -1550,12 +1545,17 @@ var BABYLON;
                         var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
-                        if (targetNode._babylonAnimationTargets) {
-                            for (var _i = 0, _a = targetNode._babylonAnimationTargets; _i < _a.length; _i++) {
-                                var babylonAnimationTarget = _a[_i];
+                        if (targetNode._babylonBones) {
+                            var babylonAnimationTargets = [targetNode._babylonMesh].concat(targetNode._babylonBones);
+                            for (var _i = 0, babylonAnimationTargets_1 = babylonAnimationTargets; _i < babylonAnimationTargets_1.length; _i++) {
+                                var babylonAnimationTarget = babylonAnimationTargets_1[_i];
                                 babylonAnimationTarget.animations.push(babylonAnimation);
                             }
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonAnimationTargets);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, babylonAnimationTargets);
+                        }
+                        else {
+                            targetNode._babylonMesh.animations.push(babylonAnimation);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonMesh);
                         }
                     }
                 });

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


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

@@ -1019,7 +1019,7 @@ declare module BABYLON.GLTF2 {
         _parent: _ILoaderNode;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
-        _babylonAnimationTargets?: Node[];
+        _babylonBones?: Bone[];
         _numMorphTargets?: number;
     }
     /** @hidden */

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

@@ -406,15 +406,13 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onCameraLoadedObservable.add(function (camera) { return _this.onCameraLoadedObservable.notifyObservers(camera); });
-            loader.onExtensionLoadedObservable.add(function (extension) {
-                _this.onExtensionLoadedObservable.notifyObservers(extension);
-                _this.onExtensionLoadedObservable.clear();
-            });
+            loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();
                 _this.onMaterialLoadedObservable.clear();
                 _this.onCameraLoadedObservable.clear();
+                _this.onExtensionLoadedObservable.clear();
                 _this.onCompleteObservable.notifyObservers(_this);
                 _this.onCompleteObservable.clear();
             });
@@ -3270,8 +3268,6 @@ var BABYLON;
                 var promises = new Array();
                 var babylonMesh = new BABYLON.Mesh(node.name || "node" + node._index, this._babylonScene, node._parent._babylonMesh);
                 node._babylonMesh = babylonMesh;
-                node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-                node._babylonAnimationTargets.push(babylonMesh);
                 GLTFLoader._LoadTransform(node, babylonMesh);
                 if (node.mesh != undefined) {
                     var mesh = GLTFLoader._GetProperty(context + "/mesh", this._gltf.meshes, node.mesh);
@@ -3535,8 +3531,8 @@ var BABYLON;
                 var boneIndex = skin.joints.indexOf(node._index);
                 babylonBone = new BABYLON.Bone(node.name || "joint" + node._index, skin._babylonSkeleton, babylonParentBone, this._getNodeMatrix(node), null, null, boneIndex);
                 babylonBones[node._index] = babylonBone;
-                node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-                node._babylonAnimationTargets.push(babylonBone);
+                node._babylonBones = node._babylonBones || [];
+                node._babylonBones.push(babylonBone);
                 return babylonBone;
             };
             GLTFLoader.prototype._loadSkinInverseBindMatricesDataAsync = function (context, skin) {
@@ -3633,7 +3629,7 @@ var BABYLON;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
                 // Ignore animations that have no animation targets.
                 if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||
-                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonAnimationTargets)) {
+                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonMesh)) {
                     return Promise.resolve();
                 }
                 // Ignore animations targeting TRS of skinned nodes.
@@ -3749,13 +3745,12 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            var morphTargets = new Array();
                             _this._forEachPrimitive(targetNode, function (babylonMesh) {
                                 var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
-                                morphTarget.animations.push(babylonAnimation);
-                                morphTargets.push(morphTarget);
+                                var babylonAnimationClone = babylonAnimation.clone();
+                                morphTarget.animations.push(babylonAnimationClone);
+                                babylonAnimationGroup.addTargetedAnimation(babylonAnimationClone, morphTarget);
                             });
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTargets);
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -3765,12 +3760,17 @@ var BABYLON;
                         var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
-                        if (targetNode._babylonAnimationTargets) {
-                            for (var _i = 0, _a = targetNode._babylonAnimationTargets; _i < _a.length; _i++) {
-                                var babylonAnimationTarget = _a[_i];
+                        if (targetNode._babylonBones) {
+                            var babylonAnimationTargets = [targetNode._babylonMesh].concat(targetNode._babylonBones);
+                            for (var _i = 0, babylonAnimationTargets_1 = babylonAnimationTargets; _i < babylonAnimationTargets_1.length; _i++) {
+                                var babylonAnimationTarget = babylonAnimationTargets_1[_i];
                                 babylonAnimationTarget.animations.push(babylonAnimation);
                             }
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonAnimationTargets);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, babylonAnimationTargets);
+                        }
+                        else {
+                            targetNode._babylonMesh.animations.push(babylonAnimation);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonMesh);
                         }
                     }
                 });

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


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

@@ -1115,7 +1115,7 @@ declare module BABYLON.GLTF2 {
         _parent: _ILoaderNode;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
-        _babylonAnimationTargets?: Node[];
+        _babylonBones?: Bone[];
         _numMorphTargets?: number;
     }
     /** @hidden */

+ 17 - 17
dist/preview release/loaders/babylonjs.loaders.js

@@ -1406,15 +1406,13 @@ var BABYLON;
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
             loader.onCameraLoadedObservable.add(function (camera) { return _this.onCameraLoadedObservable.notifyObservers(camera); });
-            loader.onExtensionLoadedObservable.add(function (extension) {
-                _this.onExtensionLoadedObservable.notifyObservers(extension);
-                _this.onExtensionLoadedObservable.clear();
-            });
+            loader.onExtensionLoadedObservable.add(function (extension) { return _this.onExtensionLoadedObservable.notifyObservers(extension); });
             loader.onCompleteObservable.add(function () {
                 _this.onMeshLoadedObservable.clear();
                 _this.onTextureLoadedObservable.clear();
                 _this.onMaterialLoadedObservable.clear();
                 _this.onCameraLoadedObservable.clear();
+                _this.onExtensionLoadedObservable.clear();
                 _this.onCompleteObservable.notifyObservers(_this);
                 _this.onCompleteObservable.clear();
             });
@@ -4252,8 +4250,6 @@ var BABYLON;
                 var promises = new Array();
                 var babylonMesh = new BABYLON.Mesh(node.name || "node" + node._index, this._babylonScene, node._parent._babylonMesh);
                 node._babylonMesh = babylonMesh;
-                node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-                node._babylonAnimationTargets.push(babylonMesh);
                 GLTFLoader._LoadTransform(node, babylonMesh);
                 if (node.mesh != undefined) {
                     var mesh = GLTFLoader._GetProperty(context + "/mesh", this._gltf.meshes, node.mesh);
@@ -4517,8 +4513,8 @@ var BABYLON;
                 var boneIndex = skin.joints.indexOf(node._index);
                 babylonBone = new BABYLON.Bone(node.name || "joint" + node._index, skin._babylonSkeleton, babylonParentBone, this._getNodeMatrix(node), null, null, boneIndex);
                 babylonBones[node._index] = babylonBone;
-                node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-                node._babylonAnimationTargets.push(babylonBone);
+                node._babylonBones = node._babylonBones || [];
+                node._babylonBones.push(babylonBone);
                 return babylonBone;
             };
             GLTFLoader.prototype._loadSkinInverseBindMatricesDataAsync = function (context, skin) {
@@ -4615,7 +4611,7 @@ var BABYLON;
                 var targetNode = GLTFLoader._GetProperty(context + "/target/node", this._gltf.nodes, channel.target.node);
                 // Ignore animations that have no animation targets.
                 if ((channel.target.path === "weights" /* WEIGHTS */ && !targetNode._numMorphTargets) ||
-                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonAnimationTargets)) {
+                    (channel.target.path !== "weights" /* WEIGHTS */ && !targetNode._babylonMesh)) {
                     return Promise.resolve();
                 }
                 // Ignore animations targeting TRS of skinned nodes.
@@ -4731,13 +4727,12 @@ var BABYLON;
                                 value: key.value[targetIndex],
                                 outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                             }); }));
-                            var morphTargets = new Array();
                             _this._forEachPrimitive(targetNode, function (babylonMesh) {
                                 var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex);
-                                morphTarget.animations.push(babylonAnimation);
-                                morphTargets.push(morphTarget);
+                                var babylonAnimationClone = babylonAnimation.clone();
+                                morphTarget.animations.push(babylonAnimationClone);
+                                babylonAnimationGroup.addTargetedAnimation(babylonAnimationClone, morphTarget);
                             });
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTargets);
                         };
                         for (var targetIndex = 0; targetIndex < targetNode._numMorphTargets; targetIndex++) {
                             _loop_1(targetIndex);
@@ -4747,12 +4742,17 @@ var BABYLON;
                         var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
                         var babylonAnimation = new BABYLON.Animation(animationName, targetPath, 1, animationType);
                         babylonAnimation.setKeys(keys);
-                        if (targetNode._babylonAnimationTargets) {
-                            for (var _i = 0, _a = targetNode._babylonAnimationTargets; _i < _a.length; _i++) {
-                                var babylonAnimationTarget = _a[_i];
+                        if (targetNode._babylonBones) {
+                            var babylonAnimationTargets = [targetNode._babylonMesh].concat(targetNode._babylonBones);
+                            for (var _i = 0, babylonAnimationTargets_1 = babylonAnimationTargets; _i < babylonAnimationTargets_1.length; _i++) {
+                                var babylonAnimationTarget = babylonAnimationTargets_1[_i];
                                 babylonAnimationTarget.animations.push(babylonAnimation);
                             }
-                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonAnimationTargets);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, babylonAnimationTargets);
+                        }
+                        else {
+                            targetNode._babylonMesh.animations.push(babylonAnimation);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonMesh);
                         }
                     }
                 });

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


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

@@ -1122,7 +1122,7 @@ declare module BABYLON.GLTF2 {
         _parent: _ILoaderNode;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
-        _babylonAnimationTargets?: Node[];
+        _babylonBones?: Bone[];
         _numMorphTargets?: number;
     }
     /** @hidden */

+ 2 - 2
dist/preview release/loaders/package.json

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

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


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


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


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


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

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

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

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

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

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

+ 2 - 2
dist/preview release/serializers/package.json

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

+ 143 - 39
dist/preview release/viewer/babylon.viewer.d.ts

@@ -1,11 +1,12 @@
 /// <reference path="./babylon.d.ts"/>
 /// <reference path="./babylon.glTF2Interface.d.ts"/>
 /// <reference path="./babylonjs.loaders.d.ts"/>
+declare module "babylonjs-loaders"{ export=BABYLON;}
 
 // Generated by dts-bundle v0.7.3
 // Dependencies for this module:
-//   ../../Tools/Gulp/babylonjs
-//   ../../Tools/Gulp/babylonjs-loaders
+//   ../../tools/Gulp/babylonjs
+//   ../../tools/Gulp/babylonjs-loaders
 
 declare module BabylonViewer {
     
@@ -185,7 +186,7 @@ declare module BabylonViewer {
                 * The scene will automatically be cleared of the old models, if exist.
                 * @param model the configuration object (or URL) to load.
                 */
-            loadModel(model?: any): Promise<ViewerModel>;
+            loadModel(model?: string | IModelConfiguration): Promise<ViewerModel>;
             /**
                 * Show the overlay and the defined sub-screen.
                 * Mainly used for help and errors
@@ -526,8 +527,11 @@ declare module BabylonViewer {
             INIT = 0,
             LOADING = 1,
             LOADED = 2,
-            CANCELED = 3,
-            ERROR = 4,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7,
     }
     /**
         * The viewer model is a container for all assets representing a sngle loaded model.
@@ -572,6 +576,10 @@ declare module BabylonViewer {
                     exception: any;
             }>;
             /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: BABYLON.Observable<ViewerModel>;
+            /**
                 * Observers registered here will be executed every time the model is being configured.
                 * This can be used to extend the model's configuration without extending the class itself
                 */
@@ -590,6 +598,7 @@ declare module BabylonViewer {
                 * Set whether this model is enabled or not.
                 */
             enabled: boolean;
+            loaderDone: boolean;
             /**
                 * Get the viewer showing this model
                 */
@@ -606,7 +615,6 @@ declare module BabylonViewer {
                 * get the list of meshes (excluding the root mesh)
                 */
             readonly meshes: BABYLON.AbstractMesh[];
-            get: any;
             /**
                 * (Re-)set the model's entire configuration
                 * @param newConfiguration the new configuration to replace the new one
@@ -644,6 +652,19 @@ declare module BabylonViewer {
                 */
             playAnimation(name: string): IModelAnimation;
             /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: BABYLON.Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
                 * Will remove this model from the viewer (but NOT dispose it).
                 */
             remove(): void;
@@ -657,16 +678,16 @@ declare module BabylonViewer {
 declare module BabylonViewer {
     
     /**
-        * Animation play mode enum - is the animation looping or playing once
+        * BABYLON.Animation play mode enum - is the animation looping or playing once
         */
-    export enum AnimationPlayMode {
+    export const enum AnimationPlayMode {
             ONCE = 0,
             LOOP = 1,
     }
     /**
         * An enum representing the current state of an animation object
         */
-    export enum AnimationState {
+    export const enum AnimationState {
             INIT = 0,
             PLAYING = 1,
             PAUSED = 2,
@@ -674,6 +695,46 @@ declare module BabylonViewer {
             ENDED = 4,
     }
     /**
+        * The different type of easing functions available
+        */
+    export const enum EasingFunction {
+            Linear = 0,
+            CircleEase = 1,
+            BackEase = 2,
+            BounceEase = 3,
+            CubicEase = 4,
+            ElasticEase = 5,
+            ExponentialEase = 6,
+            PowerEase = 7,
+            QuadraticEase = 8,
+            QuarticEase = 9,
+            QuinticEase = 10,
+            SineEase = 11,
+    }
+    /**
+        * Defines a simple animation to be applied to a model (scale).
+        */
+    export interface ModelAnimationConfiguration {
+            /**
+                * Time of animation, in seconds
+                */
+            time: number;
+            /**
+                * Scale to apply
+                */
+            scaling?: BABYLON.Vector3;
+            /**
+                * Easing function to apply
+                * See SPECTRE.EasingFunction
+                */
+            easingFunction?: number;
+            /**
+                * An Easing mode to apply to the easing function
+                * See BABYLON.EasingFunction
+                */
+            easingMode?: number;
+    }
+    /**
         * This interface can be implemented to define new types of ModelAnimation objects.
         */
     export interface IModelAnimation {
@@ -699,7 +760,7 @@ declare module BabylonViewer {
                 */
             readonly currentFrame: number;
             /**
-                * Animation's FPS value
+                * BABYLON.Animation's FPS value
                 */
             readonly fps: number;
             /**
@@ -855,6 +916,7 @@ declare module BabylonViewer {
 declare module BabylonViewer {
     
     
+    export function getConfigurationKey(key: string, configObject: any): any;
     export interface ViewerConfiguration {
             version?: string;
             extends?: string;
@@ -876,6 +938,7 @@ declare module BabylonViewer {
                     [name: string]: boolean | ILightConfiguration;
             };
             engine?: {
+                    renderInBackground?: boolean;
                     antialiasing?: boolean;
                     disableResize?: boolean;
                     engineOptions?: BABYLON.EngineOptions;
@@ -917,7 +980,12 @@ declare module BabylonViewer {
                             };
                     };
                     hideLoadingDelay?: number;
-                    environmentAssetsRootURL?: string;
+                    assetsRootURL?: string;
+                    environmentMainColor?: {
+                            r: number;
+                            g: number;
+                            b: number;
+                    };
                     environmentMap?: {
                             /**
                                 * Environment map texture path in relative to the asset folder.
@@ -932,26 +1000,60 @@ declare module BabylonViewer {
                                 */
                             tintLevel: number;
                     };
-                    renderingPipelines?: {
-                            default?: boolean | {
-                                    [propName: string]: any;
-                            };
-                            standard?: boolean | {
-                                    [propName: string]: any;
-                            };
-                            ssao?: boolean | {
-                                    [propName: string]: any;
-                            };
-                            ssao2?: boolean | {
-                                    [propName: string]: any;
-                            };
-                    };
+                    defaultRenderingPipelines?: boolean | IDefaultRenderingPipelineConfiguration;
+            };
+    }
+    /**
+        * Defines an animation to be applied to a model (translation, scale or rotation).
+        */
+    export interface IModelAnimationConfiguration {
+            /**
+                * Time of animation, in seconds
+                */
+            time?: number;
+            /**
+                * Scale to apply
+                */
+            scaling?: {
+                    x: number;
+                    y: number;
+                    z: number;
             };
+            /**
+                * Easing function to apply
+                * See SPECTRE.EasingFunction
+                */
+            easingFunction?: number;
+            /**
+                * An Easing mode to apply to the easing function
+                * See BABYLON.EasingFunction
+                */
+            easingMode?: number;
+    }
+    export interface IDefaultRenderingPipelineConfiguration {
+            sharpenEnabled?: boolean;
+            bloomEnabled?: boolean;
+            bloomThreshold?: number;
+            depthOfFieldEnabled?: boolean;
+            depthOfFieldBlurLevel?: BABYLON.DepthOfFieldEffectBlurLevel;
+            fxaaEnabled?: boolean;
+            imageProcessingEnabled?: boolean;
+            defaultPipelineTextureType?: number;
+            bloomScale?: number;
+            chromaticAberrationEnabled?: boolean;
+            grainEnabled?: boolean;
+            bloomKernel?: number;
+            hardwareScaleLevel?: number;
+            bloomWeight?: number;
+            bllomThreshold?: number;
+            hdr?: boolean;
+            samples?: number;
     }
     export interface IModelConfiguration {
             id?: string;
             url?: string;
             root?: string;
+            file?: string;
             loader?: string;
             position?: {
                     x: number;
@@ -984,6 +1086,8 @@ declare module BabylonViewer {
                     autoStart?: boolean | string;
                     playOnce?: boolean;
             };
+            entryAnimation?: IModelAnimationConfiguration;
+            exitAnimation?: IModelAnimationConfiguration;
             material?: {
                     directEnabled?: boolean;
                     directIntensity?: number;
@@ -1191,6 +1295,7 @@ declare module BabylonViewer {
                     renderTarget?: ISceneOptimizerParameters;
                     mergeMeshes?: ISceneOptimizerParameters;
             };
+            custom?: string;
     }
     export interface IObserversConfiguration {
             onEngineInit?: string;
@@ -1632,6 +1737,7 @@ declare module BabylonViewer {
                 * Please be careful when using labs in production.
                 */
             labs: ViewerLabs;
+            readonly defaultRenderingPipeline: BABYLON.Nullable<BABYLON.DefaultRenderingPipeline>;
             constructor(_viewer: AbstractViewer);
             /**
                 * Returns a boolean representing HDR support
@@ -1641,6 +1747,8 @@ declare module BabylonViewer {
                 * Return the main color defined in the configuration.
                 */
             readonly mainColor: BABYLON.Color3;
+            readonly reflectionColor: BABYLON.Color3;
+            animationBlendingEnabled: boolean;
             /**
                 * Should shadows be rendered every frame, or only once and stop.
                 * This can be used to optimize a scene.
@@ -1649,19 +1757,18 @@ declare module BabylonViewer {
                 * @param process if true shadows will be updated once every frame. if false they will stop being updated.
                 */
             processShadows: boolean;
+            groundEnabled: boolean;
+            /**
+                * sets wether the reflection is disabled.
+                */
+            groundMirrorEnabled: boolean;
+            defaultRenderingPipelineEnabled: boolean;
             /**
                 * Sets the engine flags to unlock all babylon features.
                 * Can also be configured using the scene.flags configuration object
                 */
             unlockBabylonFeatures(): void;
             /**
-                * initialize the environment for a specific model.
-                * Per default it will use the viewer's configuration.
-                * @param model the model to use to configure the environment.
-                * @returns a Promise that will resolve when the configuration is done.
-                */
-            protected _initEnvironment(model?: ViewerModel): Promise<BABYLON.Scene>;
-            /**
                 * initialize the scene. Calling this function again will dispose the old scene, if exists.
                 */
             initScene(sceneConfiguration?: ISceneConfiguration, optimizerConfiguration?: boolean | ISceneOptimizerConfiguration): Promise<BABYLON.Scene>;
@@ -1672,6 +1779,8 @@ declare module BabylonViewer {
                 * @param globalConfiguration The global configuration object, after the new configuration was merged into it
                 */
             updateConfiguration(newConfiguration: Partial<ViewerConfiguration>, globalConfiguration: ViewerConfiguration, model?: ViewerModel): void;
+            bloomEnabled: boolean;
+            fxaaEnabled: boolean;
             /**
                 * internally configure the scene using the provided configuration.
                 * The scene will not be recreated, but just updated.
@@ -1685,11 +1794,6 @@ declare module BabylonViewer {
                 */
             protected _configureOptimizer(optimizerConfig: ISceneOptimizerConfiguration | boolean): void;
             /**
-                * configure all models using the configuration.
-                * @param modelConfiguration the configuration to use to reconfigure the models
-                */
-            protected _configureModel(modelConfiguration: Partial<IModelConfiguration>): void;
-            /**
                 * (Re) configure the camera. The camera will only be created once and from this point will only be reconfigured.
                 * @param cameraConfig the new camera configuration
                 * @param model optionally use the model to configure the camera.
@@ -1790,7 +1894,7 @@ declare module BabylonViewer {
     
     export class ViewerLabs {
             constructor(_sceneManager: SceneManager);
-            environmentAssetsRootURL: string;
+            assetsRootURL: string;
             environment: PBREnvironment;
             /**
                         * Loads an environment map from a given URL
@@ -1826,7 +1930,7 @@ declare module BabylonViewer {
                 * @param url Asset url
                 * @returns The Asset url using the `environmentAssetsRootURL` if the url is not an absolute path.
                 */
-            getEnvironmentAssetUrl(url: string): string;
+            getAssetUrl(url: string): string;
     }
 }
 

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


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


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

@@ -1,11 +1,12 @@
 /// <reference path="./babylon.d.ts"/>
 /// <reference path="./babylon.glTF2Interface.d.ts"/>
 /// <reference path="./babylonjs.loaders.d.ts"/>
+declare module "babylonjs-loaders"{ export=BABYLON;}
 
 // Generated by dts-bundle v0.7.3
 // Dependencies for this module:
-//   ../../Tools/Gulp/babylonjs
-//   ../../Tools/Gulp/babylonjs-loaders
+//   ../../tools/Gulp/babylonjs
+//   ../../tools/Gulp/babylonjs-loaders
 
 declare module 'babylonjs-viewer' {
     import { mapperManager } from 'babylonjs-viewer/configuration/mappers';
@@ -145,7 +146,7 @@ declare module 'babylonjs-viewer/viewer/viewerManager' {
 }
 
 declare module 'babylonjs-viewer/viewer/defaultViewer' {
-    import { ViewerConfiguration } from 'babylonjs-viewer/configuration/configuration';
+    import { ViewerConfiguration, IModelConfiguration } from 'babylonjs-viewer/configuration/configuration';
     import { Template } from 'babylonjs-viewer/templateManager';
     import { AbstractViewer } from 'babylonjs-viewer/viewer/viewer';
     import { ViewerModel } from 'babylonjs-viewer/model/viewerModel';
@@ -185,7 +186,7 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * The scene will automatically be cleared of the old models, if exist.
                 * @param model the configuration object (or URL) to load.
                 */
-            loadModel(model?: any): Promise<ViewerModel>;
+            loadModel(model?: string | IModelConfiguration): Promise<ViewerModel>;
             /**
                 * Show the overlay and the defined sub-screen.
                 * Mainly used for help and errors
@@ -517,7 +518,7 @@ declare module 'babylonjs-viewer/loader/modelLoader' {
 }
 
 declare module 'babylonjs-viewer/model/viewerModel' {
-    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, AbstractMesh, Observable, SceneLoaderProgressEvent, ParticleSystem, Skeleton, IDisposable, Nullable } from "babylonjs";
+    import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, AbstractMesh, Observable, SceneLoaderProgressEvent, ParticleSystem, Skeleton, IDisposable, Nullable, Animation } from "babylonjs";
     import { GLTF2 } from "babylonjs-loaders";
     import { IModelConfiguration } from "babylonjs-viewer/configuration/configuration";
     import { IModelAnimation } from "babylonjs-viewer/model/modelAnimation";
@@ -526,8 +527,11 @@ declare module 'babylonjs-viewer/model/viewerModel' {
             INIT = 0,
             LOADING = 1,
             LOADED = 2,
-            CANCELED = 3,
-            ERROR = 4,
+            ENTRY = 3,
+            ENTRYDONE = 4,
+            COMPLETE = 5,
+            CANCELED = 6,
+            ERROR = 7,
     }
     /**
         * The viewer model is a container for all assets representing a sngle loaded model.
@@ -572,6 +576,10 @@ declare module 'babylonjs-viewer/model/viewerModel' {
                     exception: any;
             }>;
             /**
+                * Will be executed after the model finished loading and complete, including entry animation and lod
+                */
+            onCompleteObservable: Observable<ViewerModel>;
+            /**
                 * Observers registered here will be executed every time the model is being configured.
                 * This can be used to extend the model's configuration without extending the class itself
                 */
@@ -590,6 +598,7 @@ declare module 'babylonjs-viewer/model/viewerModel' {
                 * Set whether this model is enabled or not.
                 */
             enabled: boolean;
+            loaderDone: boolean;
             /**
                 * Get the viewer showing this model
                 */
@@ -606,7 +615,6 @@ declare module 'babylonjs-viewer/model/viewerModel' {
                 * get the list of meshes (excluding the root mesh)
                 */
             readonly meshes: AbstractMesh[];
-            get: any;
             /**
                 * (Re-)set the model's entire configuration
                 * @param newConfiguration the new configuration to replace the new one
@@ -644,6 +652,19 @@ declare module 'babylonjs-viewer/model/viewerModel' {
                 */
             playAnimation(name: string): IModelAnimation;
             /**
+             * Begin @animations with the specified @easingFunction
+             * @param animations The BABYLON Animations to begin
+             * @param duration of transition, in seconds
+             * @param easingFunction An easing function to apply
+             * @param easingMode A easing mode to apply to the easingFunction
+             * @param onAnimationEnd Call back trigger at the end of the animation.
+             */
+            transitionTo(animations: Animation[], duration: number, easingFunction: any, easingMode: number | undefined, onAnimationEnd: () => void): void;
+            /**
+                * Stops and removes all animations that have been applied to the model
+                */
+            stopAllAnimations(): void;
+            /**
                 * Will remove this model from the viewer (but NOT dispose it).
                 */
             remove(): void;
@@ -655,18 +676,18 @@ declare module 'babylonjs-viewer/model/viewerModel' {
 }
 
 declare module 'babylonjs-viewer/model/modelAnimation' {
-    import { AnimationGroup } from "babylonjs";
+    import { AnimationGroup, Vector3 } from "babylonjs";
     /**
         * Animation play mode enum - is the animation looping or playing once
         */
-    export enum AnimationPlayMode {
+    export const enum AnimationPlayMode {
             ONCE = 0,
             LOOP = 1,
     }
     /**
         * An enum representing the current state of an animation object
         */
-    export enum AnimationState {
+    export const enum AnimationState {
             INIT = 0,
             PLAYING = 1,
             PAUSED = 2,
@@ -674,6 +695,46 @@ declare module 'babylonjs-viewer/model/modelAnimation' {
             ENDED = 4,
     }
     /**
+        * The different type of easing functions available
+        */
+    export const enum EasingFunction {
+            Linear = 0,
+            CircleEase = 1,
+            BackEase = 2,
+            BounceEase = 3,
+            CubicEase = 4,
+            ElasticEase = 5,
+            ExponentialEase = 6,
+            PowerEase = 7,
+            QuadraticEase = 8,
+            QuarticEase = 9,
+            QuinticEase = 10,
+            SineEase = 11,
+    }
+    /**
+        * Defines a simple animation to be applied to a model (scale).
+        */
+    export interface ModelAnimationConfiguration {
+            /**
+                * Time of animation, in seconds
+                */
+            time: number;
+            /**
+                * Scale to apply
+                */
+            scaling?: Vector3;
+            /**
+                * Easing function to apply
+                * See SPECTRE.EasingFunction
+                */
+            easingFunction?: number;
+            /**
+                * An Easing mode to apply to the easing function
+                * See BABYLON.EasingFunction
+                */
+            easingMode?: number;
+    }
+    /**
         * This interface can be implemented to define new types of ModelAnimation objects.
         */
     export interface IModelAnimation {
@@ -854,7 +915,8 @@ declare module 'babylonjs-viewer/initializer' {
 
 declare module 'babylonjs-viewer/configuration/configuration' {
     import { ITemplateConfiguration } from 'babylonjs-viewer/templateManager';
-    import { EngineOptions, IGlowLayerOptions } from 'babylonjs';
+    import { EngineOptions, IGlowLayerOptions, DepthOfFieldEffectBlurLevel } from 'babylonjs';
+    export function getConfigurationKey(key: string, configObject: any): any;
     export interface ViewerConfiguration {
             version?: string;
             extends?: string;
@@ -876,6 +938,7 @@ declare module 'babylonjs-viewer/configuration/configuration' {
                     [name: string]: boolean | ILightConfiguration;
             };
             engine?: {
+                    renderInBackground?: boolean;
                     antialiasing?: boolean;
                     disableResize?: boolean;
                     engineOptions?: EngineOptions;
@@ -917,7 +980,12 @@ declare module 'babylonjs-viewer/configuration/configuration' {
                             };
                     };
                     hideLoadingDelay?: number;
-                    environmentAssetsRootURL?: string;
+                    assetsRootURL?: string;
+                    environmentMainColor?: {
+                            r: number;
+                            g: number;
+                            b: number;
+                    };
                     environmentMap?: {
                             /**
                                 * Environment map texture path in relative to the asset folder.
@@ -932,26 +1000,60 @@ declare module 'babylonjs-viewer/configuration/configuration' {
                                 */
                             tintLevel: number;
                     };
-                    renderingPipelines?: {
-                            default?: boolean | {
-                                    [propName: string]: any;
-                            };
-                            standard?: boolean | {
-                                    [propName: string]: any;
-                            };
-                            ssao?: boolean | {
-                                    [propName: string]: any;
-                            };
-                            ssao2?: boolean | {
-                                    [propName: string]: any;
-                            };
-                    };
+                    defaultRenderingPipelines?: boolean | IDefaultRenderingPipelineConfiguration;
             };
     }
+    /**
+        * Defines an animation to be applied to a model (translation, scale or rotation).
+        */
+    export interface IModelAnimationConfiguration {
+            /**
+                * Time of animation, in seconds
+                */
+            time?: number;
+            /**
+                * Scale to apply
+                */
+            scaling?: {
+                    x: number;
+                    y: number;
+                    z: number;
+            };
+            /**
+                * Easing function to apply
+                * See SPECTRE.EasingFunction
+                */
+            easingFunction?: number;
+            /**
+                * An Easing mode to apply to the easing function
+                * See BABYLON.EasingFunction
+                */
+            easingMode?: number;
+    }
+    export interface IDefaultRenderingPipelineConfiguration {
+            sharpenEnabled?: boolean;
+            bloomEnabled?: boolean;
+            bloomThreshold?: number;
+            depthOfFieldEnabled?: boolean;
+            depthOfFieldBlurLevel?: DepthOfFieldEffectBlurLevel;
+            fxaaEnabled?: boolean;
+            imageProcessingEnabled?: boolean;
+            defaultPipelineTextureType?: number;
+            bloomScale?: number;
+            chromaticAberrationEnabled?: boolean;
+            grainEnabled?: boolean;
+            bloomKernel?: number;
+            hardwareScaleLevel?: number;
+            bloomWeight?: number;
+            bllomThreshold?: number;
+            hdr?: boolean;
+            samples?: number;
+    }
     export interface IModelConfiguration {
             id?: string;
             url?: string;
             root?: string;
+            file?: string;
             loader?: string;
             position?: {
                     x: number;
@@ -984,6 +1086,8 @@ declare module 'babylonjs-viewer/configuration/configuration' {
                     autoStart?: boolean | string;
                     playOnce?: boolean;
             };
+            entryAnimation?: IModelAnimationConfiguration;
+            exitAnimation?: IModelAnimationConfiguration;
             material?: {
                     directEnabled?: boolean;
                     directIntensity?: number;
@@ -1191,6 +1295,7 @@ declare module 'babylonjs-viewer/configuration/configuration' {
                     renderTarget?: ISceneOptimizerParameters;
                     mergeMeshes?: ISceneOptimizerParameters;
             };
+            custom?: string;
     }
     export interface IObserversConfiguration {
             onEngineInit?: string;
@@ -1550,7 +1655,7 @@ declare module 'babylonjs-viewer/templateManager' {
 }
 
 declare module 'babylonjs-viewer/viewer/sceneManager' {
-    import { Scene, ArcRotateCamera, Light, SceneOptimizer, EnvironmentHelper, Color3, Observable } from 'babylonjs';
+    import { Scene, ArcRotateCamera, Light, SceneOptimizer, EnvironmentHelper, Color3, Observable, DefaultRenderingPipeline, Nullable } from 'babylonjs';
     import { AbstractViewer } from 'babylonjs-viewer/viewer/viewer';
     import { ILightConfiguration, ISceneConfiguration, ISceneOptimizerConfiguration, ICameraConfiguration, ISkyboxConfiguration, ViewerConfiguration, IGroundConfiguration, IModelConfiguration } from 'babylonjs-viewer/configuration/configuration';
     import { ViewerModel } from 'babylonjs-viewer/model/viewerModel';
@@ -1632,6 +1737,7 @@ declare module 'babylonjs-viewer/viewer/sceneManager' {
                 * Please be careful when using labs in production.
                 */
             labs: ViewerLabs;
+            readonly defaultRenderingPipeline: Nullable<DefaultRenderingPipeline>;
             constructor(_viewer: AbstractViewer);
             /**
                 * Returns a boolean representing HDR support
@@ -1641,6 +1747,8 @@ declare module 'babylonjs-viewer/viewer/sceneManager' {
                 * Return the main color defined in the configuration.
                 */
             readonly mainColor: Color3;
+            readonly reflectionColor: Color3;
+            animationBlendingEnabled: boolean;
             /**
                 * Should shadows be rendered every frame, or only once and stop.
                 * This can be used to optimize a scene.
@@ -1649,19 +1757,18 @@ declare module 'babylonjs-viewer/viewer/sceneManager' {
                 * @param process if true shadows will be updated once every frame. if false they will stop being updated.
                 */
             processShadows: boolean;
+            groundEnabled: boolean;
+            /**
+                * sets wether the reflection is disabled.
+                */
+            groundMirrorEnabled: boolean;
+            defaultRenderingPipelineEnabled: boolean;
             /**
                 * Sets the engine flags to unlock all babylon features.
                 * Can also be configured using the scene.flags configuration object
                 */
             unlockBabylonFeatures(): void;
             /**
-                * initialize the environment for a specific model.
-                * Per default it will use the viewer's configuration.
-                * @param model the model to use to configure the environment.
-                * @returns a Promise that will resolve when the configuration is done.
-                */
-            protected _initEnvironment(model?: ViewerModel): Promise<Scene>;
-            /**
                 * initialize the scene. Calling this function again will dispose the old scene, if exists.
                 */
             initScene(sceneConfiguration?: ISceneConfiguration, optimizerConfiguration?: boolean | ISceneOptimizerConfiguration): Promise<Scene>;
@@ -1672,6 +1779,8 @@ declare module 'babylonjs-viewer/viewer/sceneManager' {
                 * @param globalConfiguration The global configuration object, after the new configuration was merged into it
                 */
             updateConfiguration(newConfiguration: Partial<ViewerConfiguration>, globalConfiguration: ViewerConfiguration, model?: ViewerModel): void;
+            bloomEnabled: boolean;
+            fxaaEnabled: boolean;
             /**
                 * internally configure the scene using the provided configuration.
                 * The scene will not be recreated, but just updated.
@@ -1685,11 +1794,6 @@ declare module 'babylonjs-viewer/viewer/sceneManager' {
                 */
             protected _configureOptimizer(optimizerConfig: ISceneOptimizerConfiguration | boolean): void;
             /**
-                * configure all models using the configuration.
-                * @param modelConfiguration the configuration to use to reconfigure the models
-                */
-            protected _configureModel(modelConfiguration: Partial<IModelConfiguration>): void;
-            /**
                 * (Re) configure the camera. The camera will only be created once and from this point will only be reconfigured.
                 * @param cameraConfig the new camera configuration
                 * @param model optionally use the model to configure the camera.
@@ -1818,7 +1922,7 @@ declare module 'babylonjs-viewer/labs/viewerLabs' {
     import { SceneManager } from 'babylonjs-viewer/viewer/sceneManager';
     export class ViewerLabs {
             constructor(_sceneManager: SceneManager);
-            environmentAssetsRootURL: string;
+            assetsRootURL: string;
             environment: PBREnvironment;
             /**
                         * Loads an environment map from a given URL
@@ -1854,7 +1958,7 @@ declare module 'babylonjs-viewer/labs/viewerLabs' {
                 * @param url Asset url
                 * @returns The Asset url using the `environmentAssetsRootURL` if the url is not an absolute path.
                 */
-            getEnvironmentAssetUrl(url: string): string;
+            getAssetUrl(url: string): string;
     }
 }
 

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-viewer",
     "description": "A simple-to-use viewer based on BabylonJS to display 3D elements natively",
-    "version": "3.2.0-rc.2",
+    "version": "3.2.0-rc.3.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -12,6 +12,7 @@
     "main": "babylon.viewer.js",
     "files": [
         "babylon.viewer.js",
+        "babylon.viewer.max.js",
         "babylon.viewer.module.d.ts",
         "babylon.glTF2Interface.d.ts",
         "babylonjs.loaders.d.ts",

+ 59 - 61
dist/preview release/what's new.md

@@ -15,13 +15,13 @@
 - New [AssetContainer](http://doc.babylonjs.com/how_to/how_to_use_assetcontainer) class and loading methods ([trevordev](https://github.com/trevordev))
 - Added [depth of field](https://www.babylonjs-playground.com/frame.html#8F5HYV#9), [MSAA, sharpening, chromatic aberration and grain effect](https://www.babylonjs-playground.com/#Y3C0HQ#146) to the default pipeline ([trevordev](https://github.com/trevordev))
 - Added support for [animation weights](http://doc.babylonjs.com/babylon101/animations#animation-weights). Demo [here](https://www.babylonjs-playground.com/#LL5BIQ) ([deltakosh](https://github.com/deltakosh))
-- Added [sub emitters for particle system](http://doc.babylonjs.com/babylon101/particles#sub-emitters) which will spawn new particle systems when particles dies. Demo [here](https://www.babylonjs-playground.com/frame.html#9NHBCC#1) ([IbraheemOsama](https://github.com/IbraheemOsama))
+- Added [sub emitters for particle system](http://doc.babylonjs.com/babylon101/particles#sub-emitters) which will spawn new particle systems when particles die. Demo [here](https://www.babylonjs-playground.com/frame.html#9NHBCC#1) ([IbraheemOsama](https://github.com/IbraheemOsama))
 - New [Babylon.js](http://doc.babylonjs.com/resources/maya) and [glTF](http://doc.babylonjs.com/resources/maya_to_gltf) exporter for Autodesk Maya ([Noalak](https://github.com/Noalak))
-- 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))
 - New [glTF exporter](http://doc.babylonjs.com/resources/3dsmax_to_gltf) for Autodesk 3dsmax ([Noalak](https://github.com/Noalak))
+- New glTF [serializer](http://doc.babylonjs.com/extensions/gltfexporter). You can now export glTF or glb files directly from a Babylon scene ([kcoley](https://github.com/kcoley))
 - Physics - Latest production version of Oimo.js is being used - 1.0.9 ([RaananW](https://github.com/RaananW))
 - Introduces [PCF](https://doc.babylonjs.com/babylon101/shadows#percentage-closer-filtering-webgl2-only) and [PCSS](https://doc.babylonjs.com/babylon101/shadows#contact-hardening-shadow-webgl2-only) shadow support in Webgl 2 ([sebavan](https://github.com/sebavan)))
-- Introduces [PBR Specular Anti Aliasing support](https://doc.babylonjs.com/how_to/physically_based_rendering_master#specular-aliasing) ([sebavan](https://github.com/sebavan)))
+- Introduces [PBR Specular Anti Aliasing support](https://doc.babylonjs.com/how_to/physically_based_rendering_master#specular-aliasing). Demoo [here](https://www.babylonjs-playground.com/#1XJD4C) ([sebavan](https://github.com/sebavan)))
 
 ## Documentation
 
@@ -31,7 +31,7 @@
 ## Updates
 
 - Improved [animation blending](https://www.babylonjs-playground.com/#DMLMIP#1) ([deltakosh](https://github.com/deltakosh))
-- New [particle system emitter shapes](http://doc.babylonjs.com/babylon101/particles#particles-shapes): cone and sphere ([IbraheemOsama](https://github.com/IbraheemOsama))
+- New [particle system emitter shapes](http://doc.babylonjs.com/babylon101/particles#shape-emitters): cone and sphere ([IbraheemOsama](https://github.com/IbraheemOsama))
 - Added support for 16bits TGA ([deltakosh](https://github.com/deltakosh))
 - New `AnimationPropertiesOverride` class used to simplify setting animation properties on child animations. [Documentation](http://doc.babylonjs.com/babylon101/animations#overriding-properties) ([deltakosh](https://github.com/deltakosh))
 - New `Texture.UseSerializedUrlIfAny` static property to let textures serialize complete URL instead of using side by side loading ([deltakosh](https://github.com/deltakosh))
@@ -39,107 +39,105 @@
 - Added support for all RGBA orders (BGR, RGB, etc..) for the DDS loader ([deltakosh](https://github.com/deltakosh))
 - Improved [SceneOptimizer](http://doc.babylonjs.com/how_to/how_to_use_sceneoptimizer) to provide better adaptability ([deltakosh](https://github.com/deltakosh))
 - 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))
 - Added new draw modes to engine (points, lines, linesloop, linestrip, trianglestrip, trianglefan) ([benaadams](https://github.com/benaadams))
-- Added GUI Textblock.lineSpacing setter and getter to configure vertical space between lines in pixels or percentage values when working with text wrapping ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now has onSelectedMeshUnselected observable that will notify observers when the current selected mesh gets unselected
+- Added GUI `Textblock.lineSpacing` setter and getter to configure vertical space between lines in pixels or percentage values when working with text wrapping ([carloslanderas](https://github.com/carloslanderas))
+- WebVR:
+  - `VRExperienceHelper` will create an empty controller model so that controller interactions can be used while the actual model is still loading ([trevordev](https://github.com/trevordev))
+  - VRHelper now has `onSelectedMeshUnselected` observable that will notify observers when the current selected mesh gets unselected
   ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now has onBeforeCameraTeleport and onAfterCameraTeleport observables that will be notified before and after camera teleportation is triggered.
+  - VRHelper now has `onBeforeCameraTeleport` and `onAfterCameraTelepor`t observables that will be notified before and after camera teleportation is triggered.
   ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now has the public property teleportationEnabled to enable / disable camera teleportation.
+  - VRHelper now has the public property `teleportationEnabled` to enable / disable camera teleportation.
    ([carloslanderas](https://github.com/carloslanderas))
-- VRHelper now exposes onNewMeshPicked observable that will notify a PickingInfo object after meshSelectionPredicate evaluation
+  - 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))
-- Added documentation to WebVRCamera and VRExperienceHelper ([trevordev](https://github.com/trevordev))
+  - VRHelper will notify now `onSelectedMeshUnselected` observable to subscribers when the applied ray selection predicate does not produce a hit and a mesh compliant with the meshSelectionPredicate was previously selected  ([carloslanderas](https://github.com/carloslanderas))
+  - Support multiple simultaneous WebVR controller gui interactions in `VRExperienceHelper` ([trevordev](https://github.com/trevordev))
+  - Ability to set a mesh to customize the WebVR gaze tracker ([trevordev](https://github.com/trevordev))
+- `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))
-- (Viewer) There is now an option to paste payload instead of a URL for configuration ([RaananW](https://github.com/RaananW))
-- (Viewer) Models can be loaded async using JavaScript ([RaananW](https://github.com/RaananW))
-- VRHelper will notify now onSelectedMeshUnselected observable to subscribers when the applied ray selection predicate does not produce a hit and a mesh compliant with the meshSelectionPredicate was previously selected
-   ([carloslanderas](https://github.com/carloslanderas))
-- (Viewer) initScene and initEngine can now be extended. onProgress during model loading is implemented as observable. ([RaananW](https://github.com/RaananW))
-- glTF loader now supports the KHR_lights extension ([MiiBond](https://github.com/MiiBond))
-- The observable can now notify observers using promise-based callback chain. ([RaananW](https://github.com/RaananW))
+- The observables can now notify observers using promise-based callback chain ([RaananW](https://github.com/RaananW))
 - Added base64 helper functions to `Tools` ([bghgary](https://github.com/bghgary))
 - Added `createDefaultCamera` and `createDefaultLight` functions to `Scene` ([bghgary](https://github.com/bghgary))
-- Gulp process now supports multiple outputs when using webpack. ([RaananW](https://github.com/RaananW))
-- (Viewer) Scene Optimizer intergrated in viewer. ([RaananW](https://github.com/RaananW))
-- (Viewer) The viewer supports custom shaders in the configuration. ([RaananW](https://github.com/RaananW))
-- Documented PostProcessRenderEffect, DefaultRenderingPipeline, BlurPostProcess, DepthOfFieldEffect, PostProcess, PostProcessManager, Effect classes ([trevordev](https://github.com/trevordev))
+- Viewer:
+  - `initScene` and `initEngine` can now be extended. `onProgress` during model loading is implemented as observable ([RaananW](https://github.com/RaananW))
+  - There is now an option to paste payload instead of a URL for configuration ([RaananW](https://github.com/RaananW))
+  - Models can be loaded asynchronously using JavaScript ([RaananW](https://github.com/RaananW))
+  - Scene Optimizer integrated in viewer ([RaananW](https://github.com/RaananW))
+  - The viewer supports custom shaders in the configuration ([RaananW](https://github.com/RaananW))
+  - Introducing the viewer labs - testing new features ([RaananW](https://github.com/RaananW))
+  - Model can be normalized using configuration, camera is dynamically configured ([RaananW](https://github.com/RaananW))
+  - It is now possible to update parts of the configuration without recreating the objects ([RaananW](https://github.com/RaananW))
+  - Viewer supports model animations and multi-model loading ([RaananW](https://github.com/RaananW))
+  - Viewer's declaration file automatically generated ([RaananW](https://github.com/RaananW))
+- Build process:
+  - New watcher configuration for VSCode. Now the task only compiles changed files ([sebavan](https://github.com/sebavan))
+  - Gulp process now supports multiple outputs when using webpack. ([RaananW](https://github.com/RaananW))
+  - Extra/external declarations can be prepended to final declarations during build. ([RaananW](https://github.com/RaananW))
+  - Extra/external declarations can be prepended to final NPM declarations during build. ([RaananW](https://github.com/RaananW))
+  - NPM package now has a dependency system, updated during build. ([RaananW](https://github.com/RaananW))
 - SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie))
 - SPS particle parenting feature ([jbousquie](https://github.com/jbousquie))
-- (Viewer) Introducing the viewer labs - testing new features. ([RaananW](https://github.com/RaananW))
 - KeepAssets class and AssetContainer.moveAllFromScene ([HoloLite](http://www.html5gamedevs.com/profile/28694-hololite/) [trevordev](https://github.com/trevordev))
-- (Viewer) It is now possible to update parts of the configuration without rcreating the objects. Extra configuration can be loaded sync (if provided) ([RaananW](https://github.com/RaananW))
-- (Gulp) extra/external declarations can be prepended to final declarations during build. ([RaananW](https://github.com/RaananW))
-- (Viewer) Model can be normalized using configuration, camera is dynamically configured. ([RaananW](https://github.com/RaananW))
-- (Gulp) extra/external declarations can be prepended to final NPM declarations during build. ([RaananW](https://github.com/RaananW))
 - GUI.Line can have its world position set from one end or the other ([SvenFrankson](https://github.com/SvenFrankson))
 - Added FOV system to background material for zoom effects in skyboxes without adjusting camera FOV ([DavidHGillen](https://github.com/DavidHGillen))
-- Improved glTF loader by using promises for asynchronous operations. ([bghgary](https://github.com/bghgary)]
-- Improved glTF loader performance by compiling materials in parallel with downloading external resources. ([bghgary](https://github.com/bghgary)]
-- Added unit tests for the glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
+- glTF loader:
+  - glTF loader now supports the KHR_lights extension ([MiiBond](https://github.com/MiiBond))
+  - Improved glTF loader by using promises for asynchronous operations ([bghgary](https://github.com/bghgary)]
+  - Improved glTF loader performance by compiling materials in parallel with downloading external resources ([bghgary](https://github.com/bghgary)]
+  - Added unit tests for the glTF 2.0 loader ([bghgary](https://github.com/bghgary)]
+  - Added support for primitive modes to glTF 2.0 loader ([bghgary](https://github.com/bghgary)]
+  - Add support for sparse accessors to glTF 2.0 loader ([bghgary](https://github.com/bghgary))
+  - Add support for cameras to glTF 2.0 loader ([bghgary](https://github.com/bghgary)]
+  - Add support for preprocessing urls to glTF 2.0 loader ([bghgary](https://github.com/bghgary)]
+  - Added Draco mesh compression support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
+  - Added unlit material extension support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 - Added promise-based async functions to the SceneLoader, Scene.whenReadyAsync, and material.forceCompilationAsync. ([bghgary](https://github.com/bghgary)]
 - Added checks to VertexData.merge to ensure data is valid before merging. ([bghgary](https://github.com/bghgary)]
-- Ability to set a mesh to customize the webVR gaze tracker ([trevordev](https://github.com/trevordev))
-- Added promise-based async functions for initWebVRAsync and useStandingMatrixAsync ([trevordev](https://github.com/trevordev))
+- Added promise-based async functions for `initWebVRAsync` and `useStandingMatrixAsync` ([trevordev](https://github.com/trevordev))
 - Add stroke (outline) options on GUI text control ([SvenFrankson](https://github.com/SvenFrankson))
 - Add isThumbClamped option on GUI slider control ([JeanPhilippeKernel](https://github.com/JeanPhilippeKernel))
 - Add floating point texture support for RenderTargetCubeTexture ([PeapBoy](https://github.com/NicolasBuecher))
 - Support for mutli-touch when interacting with multiple gui elements simultaneously ([trevordev](https://github.com/trevordev))
-- (Viewer) Declaration file published, ready for npm. ([RaananW](https://github.com/RaananW))
-- Added Draco mesh compression support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
-- Support multiple simultaneous webVR controller gui interactions in WebVRExperienceHelper ([trevordev](https://github.com/trevordev))
-- (Viewer) XHR requests not use Tools.LoadFile and are disposed correctly - [#3671](https://github.com/BabylonJS/Babylon.js/issues/3671) ([RaananW](https://github.com/RaananW))
 - Added `Tools.WorkerPool` class for web worker management. ([bghgary](https://github.com/bghgary))
 - Support depth maps for multiple active cameras for post processes like depth of field ([trevordev](https://github.com/trevordev))
 - Integrates depth texture support in the engine ([sebavan](https://github.com/sebavan))
-- NPM package now has a dependency system, updated during build. ([RaananW](https://github.com/RaananW))
-- WebVRExperienceHelper will create an empty controller model so that controller interactions can be used while the actual model is still loading ([trevordev](https://github.com/trevordev))
 - Default fragment shader will clamp negative values to avoid underflow, webVR post processing will render to eye texture size ([trevordev](https://github.com/trevordev))
 - Supports Environment Drag and Drop in Sandbox ([sebavan](https://github.com/sebavan))
 - EnvironmentHelper has no an onError observable to handle errors when loading the textures ([RaananW](https://github.com/RaananW))
-- (Viewer) Viewer supports model animations and multi-model loading ([RaananW](https://github.com/RaananW))
 - Tests for sharpen, chromatic aberration, default pipeline and enable/disable post processes ([trevordev](https://github.com/trevordev))
 - onPointer* callbacks have now the event type as a 3rd variable ([RaananW](https://github.com/RaananW))
 - Lightmap texture in PBR material follow the gammaSpace Flag of the texture ([sebavan](https://github.com/sebavan))
 - Added setTextureFromPostProcessOutput to bind the output of a postprocess into an effect ([trevordev](https://github.com/trevordev))
-- Added support for primitive modes to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
 - Updated bloom effect to only bloom areas of the image above a luminance threshold ([trevordev](https://github.com/trevordev))
 - Cannon and Oimo are optional dependencies ([RaananW](https://github.com/RaananW))
 - Shadows - Introduces [Normal Bias](https://doc.babylonjs.com/babylon101/shadows#normal-bias-since-32) ([sebavan](https://github.com/sebavan)))
 - Earcut is an external, optional dependency. ([RaananW](https://github.com/RaananW))
 - Return animation groups when calling `SceneLoader.ImportMesh`. ([bghgary](https://github.com/bghgary)]
 - Add support for normalized and non-float data to `Buffer` and `VertexBuffer`. ([bghgary](https://github.com/bghgary)]
-- Added unlit material extension support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
-- (Viewer) Viewer's declaration file automatically generated ([RaananW](https://github.com/RaananW))
 - New serialize and parse functions for effect layers (Highlight and Glow layers) ([julien-moreau](https://github.com/julien-moreau))
 - GUI: Introduced `MultiLine` which will draw lines between any number of meshes, controls and points. [Documentation](http://doc.babylonjs.com/how_to/gui#multiline) ([royibernthal](https://github.com/royibernthal))
-- Added alphaCutOff support for StandardMaterial ([deltakosh](https://github.com/deltakosh))
-- Add support for sparse accessors to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
-- Add support for cameras to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
-- Add support for preprocessing urls to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
-- Viewer upgrade - see [PR](https://github.com/BabylonJS/Babylon.js/pull/4160) ([RaananW](https://github.com/RaananW))
-- New serialize and parse functions for SSAO2 Rendering Pipeline ([julien-moreau](https://github.com/julien-moreau))
+- Added `alphaCutOff` support for StandardMaterial ([deltakosh](https://github.com/deltakosh))
+- New `serialize` and `Parse` functions for SSAO2 Rendering Pipeline ([julien-moreau](https://github.com/julien-moreau))
 
 ## Bug fixes
 
-- `setPivotMatrix` ws not setting pivot correctly. This is now fixed. We also introduced a new `setPreTransformMatrix` to reproduce the sometimes needed behavior of the previous `setPivotMatrix` function ([deltakosh](https://github.com/deltakosh))
+- `setPivotMatrix` was not setting pivot correctly. This is now fixed. We also introduced a new `setPreTransformMatrix` to reproduce the sometimes needed behavior of the previous `setPivotMatrix` function ([deltakosh](https://github.com/deltakosh))
 - SPS solid particle `.pivot` property now also behaves like the standard mesh pivot. Former behavior (particle translation) can be kept with the particle property `.translateFromPivot` set to true ([jbousquie](https://github.com/jbousquie))
 - Texture extension detection in `Engine.CreateTexture` ([sebavan](https://github.com/sebavan))
-- SPS internal temporary vector3 instead of Tmp.Vector3 to avoid possible concurrent uses ([jbousquie](https://github.com/jbousquie))
+- SPS uses internal temporary Vector3 instead of Tmp.Vector3 to avoid possible concurrent uses ([jbousquie](https://github.com/jbousquie))
 - Fixed a bug when calling load on an empty assets manager - [#3739](https://github.com/BabylonJS/Babylon.js/issues/3739) ([RaananW](https://github.com/RaananW))
 - Enabling teleportation in the vr helper class caused a redundant post process to be added ([trevordev](https://github.com/trevordev))
 - (Viewer) Fixed a bug where loading another mesh positioned it incorrectly ([RaananW](https://github.com/RaananW))
-- Scale vr controllers by deviceScale when it is set in VRExperienceHelper ([trevordev](https://github.com/trevordev))
 - (Viewer) Disabling templates now work correctly ([RaananW](https://github.com/RaananW))
+- Scale vr controllers by deviceScale when it is set in VRExperienceHelper ([trevordev](https://github.com/trevordev))
 - AMD "define" declaration is no longer anonymous ([RaananW](https://github.com/RaananW))
 - Collision worker didn't initialize instanced meshes correctly - [#3819](https://github.com/BabylonJS/Babylon.js/issues/3819) ([RaananW](https://github.com/RaananW))
-- postMessage calls in webworkers were fixed. ([RaananW](https://github.com/RaananW))
+- `postMessage` calls in webworkers were fixed ([RaananW](https://github.com/RaananW))
 - Fixed WebCam Texture on Firefox and Edge - [#3825](https://github.com/BabylonJS/Babylon.js/issues/3825) ([sebavan](https://github.com/sebavan))
-- Add onLoadObservable on VideoTexture - [#3845](https://github.com/BabylonJS/Babylon.js/issues/3845) ([sebavan](https://github.com/sebavan))
-- beforeRender is now triggered after the camera updated its state - [#3873](https://github.com/BabylonJS/Babylon.js/issues/3873) ([RaananW](https://github.com/RaananW))
-- Tools.DeepCopy no longer copying getter-only elements - [#3929](https://github.com/BabylonJS/Babylon.js/issues/3929) ([RaananW](https://github.com/RaananW))
+- Add `onLoadObservable` on VideoTexture - [#3845](https://github.com/BabylonJS/Babylon.js/issues/3845) ([sebavan](https://github.com/sebavan))
+- `beforeRender` is now triggered after the camera updated its state - [#3873](https://github.com/BabylonJS/Babylon.js/issues/3873) ([RaananW](https://github.com/RaananW))
 - Reflection and refraction no longer apply a toLinear conversion twice when applying image processing as a post process - [#4060](https://github.com/BabylonJS/Babylon.js/issues/4060) ([trevordev](https://github.com/trevordev))
 - Fix ember.js compatibility in ```PostProcessRenderEffect``` ([sebavan](https://github.com/sebavan))
 - Fix ember.js compatibility in ```BloomEffect``` and ```Camera``` ([kaysabelle](https://github.com/kaysabelle))
@@ -147,12 +145,12 @@
 
 ## Breaking changes
 
-- Removed the unused PostProcessRenderPass class and extended postProcessingRenderingEffect to support multiple PostProcesses ([trevordev](https://github.com/trevordev))
-- VertexData.merge no longer supports merging of data that do not have the same set of attributes. ([bghgary](https://github.com/bghgary)]
+- Removed the unused `PostProcessRenderPass` class and extended `postProcessingRenderingEffect` to support multiple PostProcesses ([trevordev](https://github.com/trevordev))
+- `VertexData.merge` no longer supports merging of data that do not have the same set of attributes. ([bghgary](https://github.com/bghgary)]
 - glTF 2.0 loader now creates a mesh for each primitive instead of merging the primitives together into one mesh. If a mesh only has one primitive, the behavior is the same as before. This change only affects meshes that have multiple primitives. ([bghgary](https://github.com/bghgary)]
-- Engine's onCanvasPointerOutObservable will now return a PointerEvent instead of the Engine. ([trevordev](https://github.com/trevordev))
+- Engine's `onCanvasPointerOutObservable` will now return a PointerEvent instead of the Engine. ([trevordev](https://github.com/trevordev))
 - Removed public references to default rendering pipeline's internal post process ([trevordev](https://github.com/trevordev))
 - `Bone.setScale` does not support scaleChildren property anymore. You can use `Bone.scale` to achieve the same effect ([deltakosh](https://github.com/deltakosh))
 - Vector3 &amp; Vector4:
-    - `MinimizeInPlace` has been renamed to `minimizeInPlace`
-    - `MaximizeInPlace` has been renamed to `maximizeInPlace`
+  - `MinimizeInPlace` has been renamed to `minimizeInPlace`
+  - `MaximizeInPlace` has been renamed to `maximizeInPlace`

+ 6 - 0
inspector/src/properties.ts

@@ -121,6 +121,12 @@ module INSPECTOR {
         'PhysicsImpostor': {
             type: BABYLON.PhysicsImpostor
         },
+        'ImageProcessingConfiguration': {
+            type: BABYLON.ImageProcessingConfiguration
+        },
+        'ColorCurves': {
+            type: BABYLON.ColorCurves
+        }
     }
 
 }

+ 14 - 15
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -507,9 +507,6 @@ module BABYLON.GLTF2 {
             const babylonMesh = new Mesh(node.name || `node${node._index}`, this._babylonScene, node._parent._babylonMesh);
             node._babylonMesh = babylonMesh;
 
-            node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-            node._babylonAnimationTargets.push(babylonMesh);
-
             GLTFLoader._LoadTransform(node, babylonMesh);
 
             if (node.mesh != undefined) {
@@ -818,8 +815,8 @@ module BABYLON.GLTF2 {
             babylonBone = new Bone(node.name || `joint${node._index}`, skin._babylonSkeleton!, babylonParentBone, this._getNodeMatrix(node), null, null, boneIndex);
             babylonBones[node._index] = babylonBone;
 
-            node._babylonAnimationTargets = node._babylonAnimationTargets || [];
-            node._babylonAnimationTargets.push(babylonBone);
+            node._babylonBones = node._babylonBones || [];
+            node._babylonBones.push(babylonBone);
 
             return babylonBone;
         }
@@ -939,7 +936,7 @@ module BABYLON.GLTF2 {
 
             // Ignore animations that have no animation targets.
             if ((channel.target.path === AnimationChannelTargetPath.WEIGHTS && !targetNode._numMorphTargets) ||
-                (channel.target.path !== AnimationChannelTargetPath.WEIGHTS && !targetNode._babylonAnimationTargets)) {
+                (channel.target.path !== AnimationChannelTargetPath.WEIGHTS && !targetNode._babylonMesh)) {
                 return Promise.resolve();
             }
 
@@ -1062,14 +1059,12 @@ module BABYLON.GLTF2 {
                             outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined
                         })));
 
-                        const morphTargets = new Array<any>();
                         this._forEachPrimitive(targetNode, babylonMesh => {
                             const morphTarget = babylonMesh.morphTargetManager!.getTarget(targetIndex);
-                            morphTarget.animations.push(babylonAnimation);
-                            morphTargets.push(morphTarget);
+                            const babylonAnimationClone = babylonAnimation.clone();
+                            morphTarget.animations.push(babylonAnimationClone);
+                            babylonAnimationGroup.addTargetedAnimation(babylonAnimationClone, morphTarget);
                         });
-
-                        babylonAnimationGroup.addTargetedAnimation(babylonAnimation, morphTargets);
                     }
                 }
                 else {
@@ -1077,12 +1072,16 @@ module BABYLON.GLTF2 {
                     const babylonAnimation = new Animation(animationName, targetPath, 1, animationType);
                     babylonAnimation.setKeys(keys);
 
-                    if (targetNode._babylonAnimationTargets) {
-                        for (const babylonAnimationTarget of targetNode._babylonAnimationTargets) {
+                    if (targetNode._babylonBones) {
+                        const babylonAnimationTargets = [targetNode._babylonMesh!, ...targetNode._babylonBones];
+                        for (const babylonAnimationTarget of babylonAnimationTargets) {
                             babylonAnimationTarget.animations.push(babylonAnimation);
                         }
-
-                        babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonAnimationTargets);
+                        babylonAnimationGroup.addTargetedAnimation(babylonAnimation, babylonAnimationTargets);
+                    }
+                    else {
+                        targetNode._babylonMesh!.animations.push(babylonAnimation);
+                        babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonMesh);
                     }
                 }
             });

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

@@ -77,7 +77,7 @@ module BABYLON.GLTF2 {
         _parent: _ILoaderNode;
         _babylonMesh?: Mesh;
         _primitiveBabylonMeshes?: Mesh[];
-        _babylonAnimationTargets?: Node[];
+        _babylonBones?: Bone[];
         _numMorphTargets?: number;
     }
 

+ 2 - 5
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -592,17 +592,14 @@ module BABYLON {
             loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
             loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));
             loader.onCameraLoadedObservable.add(camera => this.onCameraLoadedObservable.notifyObservers(camera));
-
-            loader.onExtensionLoadedObservable.add(extension => {
-                this.onExtensionLoadedObservable.notifyObservers(extension);
-                this.onExtensionLoadedObservable.clear();
-            });
+            loader.onExtensionLoadedObservable.add(extension => this.onExtensionLoadedObservable.notifyObservers(extension));
 
             loader.onCompleteObservable.add(() => {
                 this.onMeshLoadedObservable.clear();
                 this.onTextureLoadedObservable.clear();
                 this.onMaterialLoadedObservable.clear();
                 this.onCameraLoadedObservable.clear();
+                this.onExtensionLoadedObservable.clear();
 
                 this.onCompleteObservable.notifyObservers(this);
                 this.onCompleteObservable.clear();

+ 1 - 1
materialsLibrary/src/cell/cell.fragment.fx

@@ -138,7 +138,7 @@ void main(void)
 	alpha *= vColor.a;
 #endif
 
-	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;;
+	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;
 
 	// Composition
 	vec4 color = vec4(finalDiffuse, alpha);

+ 2 - 1
package.json

@@ -9,7 +9,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "3.2.0-rc.2",
+    "version": "3.2.0-rc.3",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -40,6 +40,7 @@
     "readmeFilename": "README.md",
     "dependencies": {},
     "devDependencies": {
+        "base64-font-loader": "0.0.4",
         "typescript": "^2.8.1"
     }
 }

+ 1 - 1
sandbox/index.css

@@ -107,7 +107,7 @@ a {
 }
 
 #droptext {
-    position: absolute;;
+    position: absolute;
     text-align: center;
     color: #fff;
     height: 50px;

+ 1 - 7
src/Animations/babylon.animatable.ts

@@ -136,13 +136,7 @@
             var runtimeAnimations = this._runtimeAnimations;
 
             for (var index = 0; index < runtimeAnimations.length; index++) {
-                runtimeAnimations[index].reset();
-            }
-
-            // Reset to original value
-            for (index = 0; index < runtimeAnimations.length; index++) {
-                var animation = runtimeAnimations[index];
-                animation.animate(0, this.fromFrame, this.toFrame, false, this._speedRatio);
+                runtimeAnimations[index].reset(true);
             }
 
             this._localDelayOffset = null;

+ 8 - 5
src/Animations/babylon.animationGroup.ts

@@ -115,12 +115,12 @@ module BABYLON {
         /**
          * This function will normalize every animation in the group to make sure they all go from beginFrame to endFrame
          * It can add constant keys at begin or end
-         * @param beginFrame defines the new begin frame for all animations. It can't be bigger than the smallest begin frame of all animations
-         * @param endFrame defines the new end frame for all animations. It can't be smaller than the largest end frame of all animations
+         * @param beginFrame defines the new begin frame for all animations or the smallest begin frame of all animations if null (defaults to 0)
+         * @param endFrame defines the new end frame for all animations or the largest end frame of all animations if null (defaults to null)
          */
-        public normalize(beginFrame = -Number.MAX_VALUE, endFrame = Number.MAX_VALUE): AnimationGroup {
-            beginFrame = Math.max(beginFrame, this._from);
-            endFrame = Math.min(endFrame, this._to);
+        public normalize(beginFrame: Nullable<number> = 0, endFrame: Nullable<number> = null): AnimationGroup {
+            if (beginFrame == null) beginFrame = this._from;
+            if (endFrame == null) endFrame = this._to;
 
             for (var index = 0; index < this._targetedAnimations.length; index++) {
                 let targetedAnimation = this._targetedAnimations[index];
@@ -151,6 +151,9 @@ module BABYLON {
                 }
             }
 
+            this._from = beginFrame;
+            this._to = endFrame;
+
             return this;
         }
 

+ 28 - 33
src/Animations/babylon.runtimeAnimation.ts

@@ -164,8 +164,13 @@
 
         /**
          * Resets the runtime animation to the beginning
+         * @param restoreOriginal defines whether to restore the target property to the original value
          */
-        public reset(): void {
+        public reset(restoreOriginal = false): void {
+            if (restoreOriginal && this._originalValue != null) {
+                this.setValue(this._originalValue, -1);
+            }
+
             this._offsetsCache = {};
             this._highLimitsCache = {};
             this._currentFrame = 0;
@@ -212,9 +217,9 @@
         }
 
         /**
-         * Affect the interpolated value to the target
+         * Apply the interpolated value to the target
          * @param currentValue defines the value computed by the animation
-         * @param weight defines the weight to apply to this value
+         * @param weight defines the weight to apply to this value (Defaults to 1.0)
          */
         public setValue(currentValue: any, weight = 1.0): void {
             if (this._target instanceof Array) {
@@ -227,13 +232,7 @@
             }
         }
 
-        /**
-         * Sets the value of the runtime animation
-         * @param target The target property of the runtime animation
-         * @param currentValue The current value to use for the runtime animation
-         * @param weight The weight to use for the runtime animation (Defaults to 1.0)
-         */
-        private _setValue(target: any, currentValue: any, weight = 1.0): void {
+        private _setValue(target: any, currentValue: any, weight: number): void {
             // Set value
             var path: any;
             var destination: any;
@@ -258,10 +257,24 @@
             this._activeTarget = destination;
             this._weight = weight;
 
+            if (!this._originalValue) {
+                let originalValue: any;
+
+                if (destination.getRestPose && path === "_matrix") { // For bones
+                    originalValue = destination.getRestPose();
+                } else {
+                    originalValue = destination[path];
+                }
+
+                if (originalValue && originalValue.clone) {
+                    this._originalValue = originalValue.clone();
+                } else {
+                    this._originalValue = originalValue;
+                }
+            }
+
             // Blending
-            let enableBlending = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;
-            let blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
-            
+            const enableBlending = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.enableBlending : this._animation.enableBlending;
             if (enableBlending && this._blendingFactor <= 1.0) {
                 if (!this._originalBlendValue) {
                     let originalValue = destination[path];
@@ -272,27 +285,7 @@
                         this._originalBlendValue = originalValue;
                     }
                 }
-            }
 
-            if (weight !== -1.0) {
-                if (!this._originalValue) {
-                    let originalValue: any;
-
-                    if (destination.getRestPose && path === "_matrix") { // For bones
-                        originalValue = destination.getRestPose();
-                    } else {
-                        originalValue = destination[path];
-                    }
-
-                    if (originalValue.clone) {
-                        this._originalValue = originalValue.clone();
-                    } else {
-                        this._originalValue = originalValue;
-                    }
-                }
-            }
-
-            if (enableBlending && this._blendingFactor <= 1.0) {
                 if (this._originalBlendValue.m) { // Matrix
                     if (Animation.AllowMatrixDecomposeForInterpolation) {
                         if (this._currentValue) {
@@ -319,6 +312,8 @@
                         this._currentValue = currentValue;
                     }
                 }
+
+                const blendingSpeed = target && target.animationPropertiesOverride ? target.animationPropertiesOverride.blendingSpeed : this._animation.blendingSpeed;
                 this._blendingFactor += blendingSpeed;
             } else {
                 this._currentValue = currentValue;

+ 17 - 13
src/Cameras/VR/babylon.vrExperienceHelper.ts

@@ -43,6 +43,8 @@ module BABYLON {
         public _teleportationEnabled: boolean;
         public _teleportationRequestInitiated = false;
         public _teleportationBackRequestInitiated = false;
+        public _rotationRightAsked = false;
+        public _rotationLeftAsked = false;
         public _dpadPressed = true;
 
         public _activePointer = false;
@@ -93,12 +95,15 @@ module BABYLON {
             this._activePointer = false;
         }
 
-        public _updatePointerDistance(distance:number) {
+        public _updatePointerDistance(distance:number = 100) {
         }
 
         public dispose(){
             this._interactionsEnabled = false;
             this._teleportationEnabled = false;
+            if(this._gazeTracker){
+                this._gazeTracker.dispose()
+            }
         }
     }
 
@@ -172,7 +177,7 @@ module BABYLON {
             this._laserPointer.parent = mesh;
         }
 
-        public _updatePointerDistance(distance:number) {
+        public _updatePointerDistance(distance:number = 100) {
             this._laserPointer.scaling.y = distance;
             this._laserPointer.position.z = -distance / 2;  
         }
@@ -280,8 +285,6 @@ module BABYLON {
         private _floorMeshesCollection: Mesh[] = [];
         private _rotationAllowed: boolean = true;
         private _teleportBackwardsVector = new Vector3(0, -1, -1);
-        private _rotationRightAsked = false;
-        private _rotationLeftAsked = false;
         private _teleportationTarget: Mesh;
         private _isDefaultTeleportationTarget = true;
         private _postProcessMove: ImageProcessingPostProcess;
@@ -443,7 +446,7 @@ module BABYLON {
                 if (this.rightController) {
                     this.rightController._activatePointer();
                 }
-                else if (this.leftController) {
+                if (this.leftController) {
                     this.leftController._activatePointer();
                 }
             }
@@ -1157,29 +1160,29 @@ module BABYLON {
                 return;
             }
 
-            if (!this._rotationLeftAsked) {
+            if (!gazer._rotationLeftAsked) {
                 if (stateObject.x < -this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationLeftAsked = true;
+                    gazer._rotationLeftAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(false);
                     }
                 }
             } else {
                 if (stateObject.x > -this._padSensibilityDown) {
-                    this._rotationLeftAsked = false;
+                    gazer._rotationLeftAsked = false;
                 }
             }
 
-            if (!this._rotationRightAsked) {
+            if (!gazer._rotationRightAsked) {
                 if (stateObject.x > this._padSensibilityUp && gazer._dpadPressed) {
-                    this._rotationRightAsked = true;
+                    gazer._rotationRightAsked = true;
                     if (this._rotationAllowed) {
                         this._rotateCamera(true);
                     }
                 }
             } else {
                 if (stateObject.x < this._padSensibilityDown) {
-                    this._rotationRightAsked = false;
+                    gazer._rotationRightAsked = false;
                 }
             }
         }
@@ -1243,8 +1246,8 @@ module BABYLON {
                     controller.webVRController.onPadStateChangedObservable.add((stateObject) => {
                         controller._dpadPressed = stateObject.pressed;
                         if (!controller._dpadPressed) {
-                            this._rotationLeftAsked = false;
-                            this._rotationRightAsked = false;
+                            controller._rotationLeftAsked = false;
+                            controller._rotationRightAsked = false;
                             controller._teleportationBackRequestInitiated = false;
                         }
                     });
@@ -1611,6 +1614,7 @@ module BABYLON {
                 gazer._updatePointerDistance(hit.distance);        
             }
             else {
+                gazer._updatePointerDistance();   
                 gazer._gazeTracker.isVisible = false;
             }
 

+ 1 - 1
src/Engine/babylon.engine.ts

@@ -726,7 +726,7 @@
          * Returns the current version of the framework
          */
         public static get Version(): string {
-            return "3.2.0-rc.2";
+            return "3.2.0-rc.3";
         }
 
         // Updatable statics so stick with vars here

+ 0 - 0
src/Engine/babylon.nullEngine.ts


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