Browse Source

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

Guide 6 years ago
parent
commit
68fcd3ff72
100 changed files with 13731 additions and 8863 deletions
  1. 0 6
      .vscode/launch.json
  2. 1188 771
      Playground/babylon.d.txt
  3. BIN
      Playground/scenes/Trees/BroadleafBark.jpg
  4. BIN
      Playground/scenes/Trees/BroadleafBark_Normal.png
  5. BIN
      Playground/scenes/Trees/Broadleaf_Desktop_Atlas.png
  6. BIN
      Playground/scenes/Trees/Broadleaf_Desktop_Atlas_Billboards.png
  7. BIN
      Playground/scenes/Trees/Broadleaf_Desktop_Atlas_Billboards_Normal.png
  8. BIN
      Playground/scenes/Trees/Broadleaf_Desktop_Atlas_Normal.png
  9. 1 0
      Playground/scenes/Trees/rawtrees.babylon
  10. 5 5
      Playground/scripts/basic scene.js
  11. 5 3
      Playground/ts.html
  12. 2 2
      Tools/Publisher/helpers/publish.js
  13. 1 1
      Viewer/src/model/viewerModel.ts
  14. BIN
      assets/environments/studio.env
  15. 1185 761
      dist/preview release/babylon.d.ts
  16. 2 2
      dist/preview release/babylon.js
  17. 5020 3346
      dist/preview release/babylon.max.js
  18. 1 1
      dist/preview release/babylon.max.js.map
  19. 2471 1539
      dist/preview release/babylon.module.d.ts
  20. 1 1
      dist/preview release/glTF2Interface/package.json
  21. 6 4
      dist/preview release/gui/babylon.gui.d.ts
  22. 49 19
      dist/preview release/gui/babylon.gui.js
  23. 1 1
      dist/preview release/gui/babylon.gui.js.map
  24. 1 1
      dist/preview release/gui/babylon.gui.min.js
  25. 12 8
      dist/preview release/gui/babylon.gui.module.d.ts
  26. 2 2
      dist/preview release/gui/package.json
  27. 6 6
      dist/preview release/inspector/babylon.inspector.bundle.js
  28. 133 140
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  29. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  30. 13 16
      dist/preview release/inspector/babylon.inspector.d.ts
  31. 26 35
      dist/preview release/inspector/babylon.inspector.module.d.ts
  32. 6 6
      dist/preview release/inspector/package.json
  33. 1 1
      dist/preview release/inspector/readme-es6.md
  34. 41 14
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  35. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  36. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  37. 41 14
      dist/preview release/loaders/babylon.glTFFileLoader.js
  38. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  39. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  40. 12 2
      dist/preview release/loaders/babylon.objFileLoader.js
  41. 1 1
      dist/preview release/loaders/babylon.objFileLoader.js.map
  42. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  43. 53 6
      dist/preview release/loaders/babylonjs.loaders.d.ts
  44. 53 16
      dist/preview release/loaders/babylonjs.loaders.js
  45. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  46. 2 2
      dist/preview release/loaders/babylonjs.loaders.min.js
  47. 111 14
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  48. 3 3
      dist/preview release/loaders/package.json
  49. 10 0
      dist/preview release/materialsLibrary/babylon.customMaterial.js
  50. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.js.map
  51. 2 2
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  52. 4 4
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js
  53. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js.map
  54. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  55. 4 0
      dist/preview release/materialsLibrary/babylonjs.materials.d.ts
  56. 14 4
      dist/preview release/materialsLibrary/babylonjs.materials.js
  57. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.js.map
  58. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  59. 8 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  60. 2 2
      dist/preview release/materialsLibrary/package.json
  61. 1 1
      dist/preview release/package.json
  62. 1 1
      dist/preview release/packagesSizeBaseLine.json
  63. 2 2
      dist/preview release/postProcessesLibrary/package.json
  64. 2 2
      dist/preview release/proceduralTexturesLibrary/package.json
  65. 1 1
      dist/preview release/readme.md
  66. 8 3
      dist/preview release/serializers/babylon.glTF2Serializer.js
  67. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.js.map
  68. 1 1
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  69. 8 3
      dist/preview release/serializers/babylonjs.serializers.js
  70. 1 1
      dist/preview release/serializers/babylonjs.serializers.js.map
  71. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  72. 3 3
      dist/preview release/serializers/package.json
  73. 2471 1539
      dist/preview release/viewer/babylon.module.d.ts
  74. 15 1
      dist/preview release/viewer/babylon.viewer.d.ts
  75. 384 336
      dist/preview release/viewer/babylon.viewer.js
  76. 4 4
      dist/preview release/viewer/babylon.viewer.max.js
  77. 18 1
      dist/preview release/viewer/babylon.viewer.module.d.ts
  78. 111 14
      dist/preview release/viewer/babylonjs.loaders.module.d.ts
  79. 25 15
      dist/preview release/what's new.md
  80. 1 1
      gui/src/2D/advancedDynamicTexture.ts
  81. 9 3
      gui/src/2D/controls/colorpicker.ts
  82. 3 3
      gui/src/2D/controls/control.ts
  83. 2 2
      gui/src/2D/controls/inputText.ts
  84. 10 3
      gui/src/2D/controls/sliders/baseSlider.ts
  85. 9 1
      gui/src/2D/controls/virtualKeyboard.ts
  86. 20 7
      gui/src/3D/controls/control3D.ts
  87. 2 2
      inspector/src/components/actionTabs/lines/checkBoxLineComponent.tsx
  88. 8 2
      inspector/src/components/actionTabs/lines/vector2LineComponent.tsx
  89. 1 1
      inspector/src/components/actionTabs/lines/vector3LineComponent.tsx
  90. 3 1
      inspector/src/components/actionTabs/tabs/propertyGrids/animationPropertyGridComponent.tsx
  91. 3 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx
  92. 2 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx
  93. 0 80
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/axesViewerComponent.tsx
  94. 42 10
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx
  95. 0 4
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/transformNodePropertyGridComponent.tsx
  96. 28 21
      inspector/src/components/actionTabs/tabs/propertyGrids/postProcesses/defaultRenderingPipelinePropertyGridComponent.tsx
  97. 1 1
      inspector/src/components/actionTabs/tabs/propertyGrids/scenePropertyGridComponent.tsx
  98. 1 1
      inspector/src/components/actionTabs/tabs/toolsTabComponent.tsx
  99. 16 16
      inspector/src/components/replayRecorder.ts
  100. 0 0
      inspector/src/components/sceneExplorer/entities/lightTreeItemComponent.tsx

+ 0 - 6
.vscode/launch.json

@@ -15,12 +15,6 @@
             ]
         },
         {
-            "name": "Launch nullEngine",
-            "type": "node",
-            "request": "launch",
-            "program": "${workspaceFolder}/tests/nullEngine/app.js"
-        },
-        {
             "name": "Launch sandbox (Chrome)",
             "type": "chrome",
             "request": "launch",

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


BIN
Playground/scenes/Trees/BroadleafBark.jpg


BIN
Playground/scenes/Trees/BroadleafBark_Normal.png


BIN
Playground/scenes/Trees/Broadleaf_Desktop_Atlas.png


BIN
Playground/scenes/Trees/Broadleaf_Desktop_Atlas_Billboards.png


BIN
Playground/scenes/Trees/Broadleaf_Desktop_Atlas_Billboards_Normal.png


BIN
Playground/scenes/Trees/Broadleaf_Desktop_Atlas_Normal.png


File diff suppressed because it is too large
+ 1 - 0
Playground/scenes/Trees/rawtrees.babylon


+ 5 - 5
Playground/scripts/basic scene.js

@@ -13,19 +13,19 @@
     camera.attachControl(canvas, true);
 
     // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
-    var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
+    var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
 
     // Default intensity is 1. Let's dim the light a small amount
     light.intensity = 0.7;
 
-    // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
-    var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 2, scene);
+    // Our built-in 'sphere' shape.
+    var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 2, segments: 32}, scene);
 
     // Move the sphere upward 1/2 its height
     sphere.position.y = 1;
 
-    // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
-    var ground = BABYLON.Mesh.CreateGround("ground1", 6, 6, 2, scene);
+    // Our built-in 'ground' shape.
+    var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 6, height: 6}, scene);
 
     return scene;
 

+ 5 - 3
Playground/ts.html

@@ -54,9 +54,11 @@
         <!-- Extensions -->
         <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js" async></script>
         <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js" async></script>
-        <script src="https://www.babylontoolkit.com/Playground/scripts/babylon.navmesh.js"></script>
-        <script src="https://www.babylontoolkit.com/Playground/scripts/babylon.manager.js"></script>
-                               
+
+        <!-- Scene Manager -->
+        <script src="https://mackeyk24.github.io/toolkit/babylon.manager.js"></script>
+        <script src="https://mackeyk24.github.io/toolkit/babylon.navmesh.js"></script>
+
         <link href="css/index.css" rel="stylesheet" />
         <link href="css/color_ts.css" rel="stylesheet" />
     </head>

+ 2 - 2
Tools/Publisher/helpers/publish.js

@@ -10,14 +10,14 @@ function publish(version, packageName, publishPath, public) {
 
     let tag = "";
     // check for alpha or beta
-    if (version.indexOf('alpha') !== -1 || version.indexOf('beta') !== -1) {
+    if (version.indexOf('alpha') !== -1 || version.indexOf('beta') !== -1 || version.indexOf('rc') !== -1) {
         tag = ' --tag preview';
     }
 
     //publish the respected package
     var cmd = 'npm publish "' + publishPath + '"' + tag;
     if (public) {
-       cmd += " --access public";
+        cmd += " --access public";
     }
 
     if (process.env.BABYLONJSREALPUBLISH === "true") {

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

@@ -264,7 +264,7 @@ export class ViewerModel implements IDisposable {
                 let ag = new AnimationGroup("animation-" + idx, this._configurationContainer && this._configurationContainer.scene);
                 let add = false;
                 skeleton.getAnimatables().forEach((a) => {
-                    if (a.animations[0]) {
+                    if (a.animations && a.animations[0]) {
                         ag.addTargetedAnimation(a.animations[0], a);
                         add = true;
                     }

BIN
assets/environments/studio.env


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


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


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


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


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


+ 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": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 6 - 4
dist/preview release/gui/babylon.gui.d.ts

@@ -1083,7 +1083,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
@@ -1923,7 +1923,7 @@ declare module BABYLON.GUI {
         private _onPasteText;
         _draw(context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         protected _beforeRenderText(text: string): string;
         dispose(): void;
@@ -2062,6 +2062,7 @@ declare module BABYLON.GUI {
         private _h;
         private _s;
         private _v;
+        private _lastPointerDownID;
         /**
          * BABYLON.Observable raised when the value changes
          */
@@ -2102,7 +2103,7 @@ declare module BABYLON.GUI {
         private _isPointOnSquare;
         private _isPointOnWheel;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         /**
          * This function expands the color picker by creating a color picker dialog with manual
@@ -2375,6 +2376,7 @@ declare module BABYLON.GUI {
         private _isThumbClamped;
         protected _displayThumb: boolean;
         private _step;
+        private _lastPointerDownID;
         protected _effectiveBarOffset: number;
         protected _renderLeft: number;
         protected _renderTop: number;
@@ -2420,7 +2422,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         protected _updateValueFromPointer(x: number, y: number): void;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
     }
 }

+ 49 - 19
dist/preview release/gui/babylon.gui.js

@@ -1053,7 +1053,7 @@ var AdvancedDynamicTexture = /** @class */ (function (_super) {
                     });
                     continue;
                 }
-                var position = mesh.getBoundingInfo().boundingSphere.center;
+                var position = mesh.getBoundingInfo ? mesh.getBoundingInfo().boundingSphere.center : mesh.getAbsolutePosition();
                 var projectedPosition = babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["Vector3"].Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
                 if (projectedPosition.z < 0 || projectedPosition.z > 1) {
                     control.notRenderable = true;
@@ -1837,6 +1837,7 @@ var ColorPicker = /** @class */ (function (_super) {
         _this._h = 360;
         _this._s = 1;
         _this._v = 1;
+        _this._lastPointerDownID = -1;
         /**
          * Observable raised when the value changes
          */
@@ -2205,9 +2206,14 @@ var ColorPicker = /** @class */ (function (_super) {
         }
         this._updateValueFromPointer(x, y);
         this._host._capturingControl[pointerId] = this;
+        this._lastPointerDownID = pointerId;
         return true;
     };
-    ColorPicker.prototype._onPointerMove = function (target, coordinates) {
+    ColorPicker.prototype._onPointerMove = function (target, coordinates, pointerId) {
+        // Only listen to pointer move events coming from the last pointer to click on the element (To support dual vr controller interaction)
+        if (pointerId != this._lastPointerDownID) {
+            return;
+        }
         // Invert transform
         this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
         var x = this._transformedPosition.x;
@@ -2215,7 +2221,7 @@ var ColorPicker = /** @class */ (function (_super) {
         if (this._pointerIsDown) {
             this._updateValueFromPointer(x, y);
         }
-        _super.prototype._onPointerMove.call(this, target, coordinates);
+        _super.prototype._onPointerMove.call(this, target, coordinates, pointerId);
     };
     ColorPicker.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
         this._pointerIsDown = false;
@@ -5164,10 +5170,10 @@ var Control = /** @class */ (function () {
         return true;
     };
     /** @hidden */
-    Control.prototype._onPointerMove = function (target, coordinates) {
+    Control.prototype._onPointerMove = function (target, coordinates, pointerId) {
         var canNotify = this.onPointerMoveObservable.notifyObservers(coordinates, -1, target, this);
         if (canNotify && this.parent != null) {
-            this.parent._onPointerMove(target, coordinates);
+            this.parent._onPointerMove(target, coordinates, pointerId);
         }
     };
     /** @hidden */
@@ -5254,7 +5260,7 @@ var Control = /** @class */ (function () {
         }
         this._dummyVector2.copyFromFloats(x, y);
         if (type === babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["PointerEventTypes"].POINTERMOVE) {
-            this._onPointerMove(this, this._dummyVector2);
+            this._onPointerMove(this, this._dummyVector2, pointerId);
             var previousControlOver = this._host._lastControlOver[pointerId];
             if (previousControlOver && previousControlOver !== this) {
                 previousControlOver._onPointerOut(this);
@@ -7745,7 +7751,7 @@ var InputText = /** @class */ (function (_super) {
         this._isTextHighlightOn = false;
         //when write permission to clipbaord data is denied
         try {
-            ev.clipboardData.setData("text/plain", this._highlightedText);
+            ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
         }
         catch (_a) { } //pass
         this._host.clipboardData = this._highlightedText;
@@ -7760,7 +7766,7 @@ var InputText = /** @class */ (function (_super) {
         this._cursorOffset = this.text.length - this._startHighlightIndex;
         //when write permission to clipbaord data is denied
         try {
-            ev.clipboardData.setData("text/plain", this._highlightedText);
+            ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
         }
         catch (_a) { } //pass
         this._host.clipboardData = this._highlightedText;
@@ -7951,13 +7957,13 @@ var InputText = /** @class */ (function (_super) {
         this._host.focusedControl = this;
         return true;
     };
-    InputText.prototype._onPointerMove = function (target, coordinates) {
+    InputText.prototype._onPointerMove = function (target, coordinates, pointerId) {
         if (this._host.focusedControl === this && this._isPointerDown) {
             this._clickedCoordinate = coordinates.x;
             this._markAsDirty();
             this._updateValueFromCursorIndex(this._cursorOffset);
         }
-        _super.prototype._onPointerMove.call(this, target, coordinates);
+        _super.prototype._onPointerMove.call(this, target, coordinates, pointerId);
     };
     InputText.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
         this._isPointerDown = false;
@@ -9996,6 +10002,7 @@ var BaseSlider = /** @class */ (function (_super) {
         _this._isThumbClamped = false;
         _this._displayThumb = true;
         _this._step = 0;
+        _this._lastPointerDownID = -1;
         // Shared rendering info
         _this._effectiveBarOffset = 0;
         /** Observable raised when the sldier value changes */
@@ -10258,13 +10265,18 @@ var BaseSlider = /** @class */ (function (_super) {
         this._pointerIsDown = true;
         this._updateValueFromPointer(coordinates.x, coordinates.y);
         this._host._capturingControl[pointerId] = this;
+        this._lastPointerDownID = pointerId;
         return true;
     };
-    BaseSlider.prototype._onPointerMove = function (target, coordinates) {
+    BaseSlider.prototype._onPointerMove = function (target, coordinates, pointerId) {
+        // Only listen to pointer move events coming from the last pointer to click on the element (To support dual vr controller interaction)
+        if (pointerId != this._lastPointerDownID) {
+            return;
+        }
         if (this._pointerIsDown) {
             this._updateValueFromPointer(coordinates.x, coordinates.y);
         }
-        _super.prototype._onPointerMove.call(this, target, coordinates);
+        _super.prototype._onPointerMove.call(this, target, coordinates, pointerId);
     };
     BaseSlider.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
         this._pointerIsDown = false;
@@ -11647,13 +11659,19 @@ var VirtualKeyboard = /** @class */ (function (_super) {
         var panel = new _stackPanel__WEBPACK_IMPORTED_MODULE_2__["StackPanel"]();
         panel.isVertical = false;
         panel.isFocusInvisible = true;
+        var maxKey = null;
         for (var i = 0; i < keys.length; i++) {
             var properties = null;
             if (propertySets && propertySets.length === keys.length) {
                 properties = propertySets[i];
             }
-            panel.addControl(this._createKey(keys[i], properties));
+            var key = this._createKey(keys[i], properties);
+            if (!maxKey || key.heightInPixels > maxKey.heightInPixels) {
+                maxKey = key;
+            }
+            panel.addControl(key);
         }
+        panel.height = maxKey ? maxKey.height : this.defaultButtonHeight;
         this.addControl(panel);
     };
     /**
@@ -13408,6 +13426,7 @@ var Control3D = /** @class */ (function () {
     /** @hidden */
     Control3D.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
         if (this._downCount !== 0) {
+            this._downCount++;
             return false;
         }
         this._downCount++;
@@ -13420,14 +13439,21 @@ var Control3D = /** @class */ (function () {
     };
     /** @hidden */
     Control3D.prototype._onPointerUp = function (target, coordinates, pointerId, buttonIndex, notifyClick) {
-        this._downCount = 0;
+        this._downCount--;
         delete this._downPointerIds[pointerId];
-        if (notifyClick && (this._enterCount > 0 || this._enterCount === -1)) {
-            this.onPointerClickObservable.notifyObservers(new _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__["Vector3WithInfo"](coordinates, buttonIndex), -1, target, this);
+        if (this._downCount < 0) {
+            // Handle if forcePointerUp was called prior to this
+            this._downCount = 0;
+            return;
         }
-        this.onPointerUpObservable.notifyObservers(new _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__["Vector3WithInfo"](coordinates, buttonIndex), -1, target, this);
-        if (this.pointerUpAnimation) {
-            this.pointerUpAnimation();
+        if (this._downCount == 0) {
+            if (notifyClick && (this._enterCount > 0 || this._enterCount === -1)) {
+                this.onPointerClickObservable.notifyObservers(new _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__["Vector3WithInfo"](coordinates, buttonIndex), -1, target, this);
+            }
+            this.onPointerUpObservable.notifyObservers(new _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__["Vector3WithInfo"](coordinates, buttonIndex), -1, target, this);
+            if (this.pointerUpAnimation) {
+                this.pointerUpAnimation();
+            }
         }
     };
     /** @hidden */
@@ -13440,6 +13466,10 @@ var Control3D = /** @class */ (function () {
             for (var key in this._downPointerIds) {
                 this._onPointerUp(this, babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["Vector3"].Zero(), +key, 0, true);
             }
+            if (this._downCount > 0) {
+                this._downCount = 1;
+                this._onPointerUp(this, babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["Vector3"].Zero(), 0, 0, true);
+            }
         }
     };
     /** @hidden */

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


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


+ 12 - 8
dist/preview release/gui/babylon.gui.module.d.ts

@@ -1113,7 +1113,7 @@ declare module "babylonjs-gui/2D/controls/control" {
         /** @hidden */
         _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
-        _onPointerMove(target: Control, coordinates: Vector2): void;
+        _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void;
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
@@ -1988,7 +1988,7 @@ declare module "babylonjs-gui/2D/controls/inputText" {
         private _onPasteText;
         _draw(context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: Vector2): void;
+        _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         protected _beforeRenderText(text: string): string;
         dispose(): void;
@@ -2137,6 +2137,7 @@ declare module "babylonjs-gui/2D/controls/colorpicker" {
         private _h;
         private _s;
         private _v;
+        private _lastPointerDownID;
         /**
          * Observable raised when the value changes
          */
@@ -2177,7 +2178,7 @@ declare module "babylonjs-gui/2D/controls/colorpicker" {
         private _isPointOnSquare;
         private _isPointOnWheel;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: Vector2): void;
+        _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         /**
          * This function expands the color picker by creating a color picker dialog with manual
@@ -2474,6 +2475,7 @@ declare module "babylonjs-gui/2D/controls/sliders/baseSlider" {
         private _isThumbClamped;
         protected _displayThumb: boolean;
         private _step;
+        private _lastPointerDownID;
         protected _effectiveBarOffset: number;
         protected _renderLeft: number;
         protected _renderTop: number;
@@ -2519,7 +2521,7 @@ declare module "babylonjs-gui/2D/controls/sliders/baseSlider" {
         /** @hidden */
         protected _updateValueFromPointer(x: number, y: number): void;
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: Vector2): void;
+        _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
     }
 }
@@ -4929,7 +4931,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         _processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
@@ -5769,7 +5771,7 @@ declare module BABYLON.GUI {
         private _onPasteText;
         _draw(context: CanvasRenderingContext2D): void;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         protected _beforeRenderText(text: string): string;
         dispose(): void;
@@ -5908,6 +5910,7 @@ declare module BABYLON.GUI {
         private _h;
         private _s;
         private _v;
+        private _lastPointerDownID;
         /**
          * BABYLON.Observable raised when the value changes
          */
@@ -5948,7 +5951,7 @@ declare module BABYLON.GUI {
         private _isPointOnSquare;
         private _isPointOnWheel;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         /**
          * This function expands the color picker by creating a color picker dialog with manual
@@ -6221,6 +6224,7 @@ declare module BABYLON.GUI {
         private _isThumbClamped;
         protected _displayThumb: boolean;
         private _step;
+        private _lastPointerDownID;
         protected _effectiveBarOffset: number;
         protected _renderLeft: number;
         protected _renderTop: number;
@@ -6266,7 +6270,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         protected _updateValueFromPointer(x: number, y: number): void;
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
-        _onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
+        _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
     }
 }

+ 2 - 2
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": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-beta.3"
+        "babylonjs": "4.0.0-rc.1"
     },
     "engines": {
         "node": "*"

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


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


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


+ 13 - 16
dist/preview release/inspector/babylon.inspector.d.ts

@@ -259,11 +259,15 @@ declare module INSPECTOR {
     interface INumericInputComponentProps {
         label: string;
         value: number;
+        step?: number;
         onChange: (value: number) => void;
     }
     export class NumericInputComponent extends React.Component<INumericInputComponentProps, {
         value: string;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: INumericInputComponentProps);
         shouldComponentUpdate(nextProps: INumericInputComponentProps, nextState: {
@@ -304,6 +308,7 @@ declare module INSPECTOR {
         label: string;
         target: any;
         propertyName: string;
+        step?: number;
         onChange?: (newvalue: BABYLON.Vector3) => void;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
     }
@@ -311,6 +316,9 @@ declare module INSPECTOR {
         isExpanded: boolean;
         value: BABYLON.Vector3;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: IVector3LineComponentProps);
         shouldComponentUpdate(nextProps: IVector3LineComponentProps, nextState: {
@@ -515,6 +523,7 @@ declare module INSPECTOR {
         label: string;
         target: any;
         propertyName: string;
+        step?: number;
         onChange?: (newvalue: BABYLON.Vector2) => void;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
     }
@@ -522,6 +531,9 @@ declare module INSPECTOR {
         isExpanded: boolean;
         value: BABYLON.Vector2;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: IVector2LineComponentProps);
         shouldComponentUpdate(nextProps: IVector2LineComponentProps, nextState: {
@@ -689,22 +701,6 @@ declare module INSPECTOR {
     }
 }
 declare module INSPECTOR {
-    interface IAxisViewerComponentProps {
-        node: BABYLON.TransformNode;
-        globalState: GlobalState;
-    }
-    export class AxesViewerComponent extends React.Component<IAxisViewerComponentProps, {
-        displayAxis: boolean;
-    }> {
-        constructor(props: IAxisViewerComponentProps);
-        shouldComponentUpdate(nextProps: IAxisViewerComponentProps, nextState: {
-            displayAxis: boolean;
-        }): boolean;
-        displayAxes(): void;
-        render(): JSX.Element;
-    }
-}
-declare module INSPECTOR {
     interface IMeshPropertyGridComponentProps {
         globalState: GlobalState;
         mesh: BABYLON.Mesh;
@@ -720,6 +716,7 @@ declare module INSPECTOR {
         renderNormalVectors(): void;
         displayNormals(): void;
         onMaterialLink(): void;
+        onSourceMeshLink(): void;
         convertPhysicsTypeToString(): string;
         render(): JSX.Element;
     }

+ 26 - 35
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -297,11 +297,15 @@ declare module "babylonjs-inspector/components/actionTabs/lines/numericInputComp
     interface INumericInputComponentProps {
         label: string;
         value: number;
+        step?: number;
         onChange: (value: number) => void;
     }
     export class NumericInputComponent extends React.Component<INumericInputComponentProps, {
         value: string;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: INumericInputComponentProps);
         shouldComponentUpdate(nextProps: INumericInputComponentProps, nextState: {
@@ -350,6 +354,7 @@ declare module "babylonjs-inspector/components/actionTabs/lines/vector3LineCompo
         label: string;
         target: any;
         propertyName: string;
+        step?: number;
         onChange?: (newvalue: Vector3) => void;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
     }
@@ -357,6 +362,9 @@ declare module "babylonjs-inspector/components/actionTabs/lines/vector3LineCompo
         isExpanded: boolean;
         value: Vector3;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: IVector3LineComponentProps);
         shouldComponentUpdate(nextProps: IVector3LineComponentProps, nextState: {
@@ -611,6 +619,7 @@ declare module "babylonjs-inspector/components/actionTabs/lines/vector2LineCompo
         label: string;
         target: any;
         propertyName: string;
+        step?: number;
         onChange?: (newvalue: Vector2) => void;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
     }
@@ -618,6 +627,9 @@ declare module "babylonjs-inspector/components/actionTabs/lines/vector2LineCompo
         isExpanded: boolean;
         value: Vector2;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: IVector2LineComponentProps);
         shouldComponentUpdate(nextProps: IVector2LineComponentProps, nextState: {
@@ -848,25 +860,6 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/cam
         render(): JSX.Element;
     }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/meshes/axesViewerComponent" {
-    import * as React from "react";
-    import { TransformNode } from "babylonjs/Meshes/transformNode";
-    import { GlobalState } from "babylonjs-inspector/components/globalState";
-    interface IAxisViewerComponentProps {
-        node: TransformNode;
-        globalState: GlobalState;
-    }
-    export class AxesViewerComponent extends React.Component<IAxisViewerComponentProps, {
-        displayAxis: boolean;
-    }> {
-        constructor(props: IAxisViewerComponentProps);
-        shouldComponentUpdate(nextProps: IAxisViewerComponentProps, nextState: {
-            displayAxis: boolean;
-        }): boolean;
-        displayAxes(): void;
-        render(): JSX.Element;
-    }
-}
 declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent" {
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
@@ -889,6 +882,7 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/mes
         renderNormalVectors(): void;
         displayNormals(): void;
         onMaterialLink(): void;
+        onSourceMeshLink(): void;
         convertPhysicsTypeToString(): string;
         render(): JSX.Element;
     }
@@ -2456,11 +2450,15 @@ declare module INSPECTOR {
     interface INumericInputComponentProps {
         label: string;
         value: number;
+        step?: number;
         onChange: (value: number) => void;
     }
     export class NumericInputComponent extends React.Component<INumericInputComponentProps, {
         value: string;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: INumericInputComponentProps);
         shouldComponentUpdate(nextProps: INumericInputComponentProps, nextState: {
@@ -2501,6 +2499,7 @@ declare module INSPECTOR {
         label: string;
         target: any;
         propertyName: string;
+        step?: number;
         onChange?: (newvalue: BABYLON.Vector3) => void;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
     }
@@ -2508,6 +2507,9 @@ declare module INSPECTOR {
         isExpanded: boolean;
         value: BABYLON.Vector3;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: IVector3LineComponentProps);
         shouldComponentUpdate(nextProps: IVector3LineComponentProps, nextState: {
@@ -2712,6 +2714,7 @@ declare module INSPECTOR {
         label: string;
         target: any;
         propertyName: string;
+        step?: number;
         onChange?: (newvalue: BABYLON.Vector2) => void;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
     }
@@ -2719,6 +2722,9 @@ declare module INSPECTOR {
         isExpanded: boolean;
         value: BABYLON.Vector2;
     }> {
+        static defaultProps: {
+            step: number;
+        };
         private _localChange;
         constructor(props: IVector2LineComponentProps);
         shouldComponentUpdate(nextProps: IVector2LineComponentProps, nextState: {
@@ -2886,22 +2892,6 @@ declare module INSPECTOR {
     }
 }
 declare module INSPECTOR {
-    interface IAxisViewerComponentProps {
-        node: BABYLON.TransformNode;
-        globalState: GlobalState;
-    }
-    export class AxesViewerComponent extends React.Component<IAxisViewerComponentProps, {
-        displayAxis: boolean;
-    }> {
-        constructor(props: IAxisViewerComponentProps);
-        shouldComponentUpdate(nextProps: IAxisViewerComponentProps, nextState: {
-            displayAxis: boolean;
-        }): boolean;
-        displayAxes(): void;
-        render(): JSX.Element;
-    }
-}
-declare module INSPECTOR {
     interface IMeshPropertyGridComponentProps {
         globalState: GlobalState;
         mesh: BABYLON.Mesh;
@@ -2917,6 +2907,7 @@ declare module INSPECTOR {
         renderNormalVectors(): void;
         displayNormals(): void;
         onMaterialLink(): void;
+        onSourceMeshLink(): void;
         convertPhysicsTypeToString(): string;
         render(): JSX.Element;
     }

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -31,11 +31,11 @@
     "dependencies": {
         "@types/react": "~16.7.3",
         "@types/react-dom": "~16.0.9",
-        "babylonjs": "4.0.0-beta.3",
-        "babylonjs-gui": "4.0.0-beta.3",
-        "babylonjs-loaders": "4.0.0-beta.3",
-        "babylonjs-serializers": "4.0.0-beta.3",
-        "babylonjs-gltf2interface": "4.0.0-beta.3"
+        "babylonjs": "4.0.0-rc.1",
+        "babylonjs-gui": "4.0.0-rc.1",
+        "babylonjs-loaders": "4.0.0-rc.1",
+        "babylonjs-serializers": "4.0.0-rc.1",
+        "babylonjs-gltf2interface": "4.0.0-rc.1"
     },
     "engines": {
         "node": "*"

+ 1 - 1
dist/preview release/inspector/readme-es6.md

@@ -20,7 +20,7 @@ import "@babylonjs/core/Debug/debugLayer";
 import "@babylonjs/inspector";
 ```
 
-The first line will ensure you can access the property debugLayer of the scene while the second will ensure the inspector can be use within your scene.
+The first line will ensure you can access the property debugLayer of the scene while the second will ensure the inspector can be used within your scene.
 
 This is a great example where code splitting or conditional loading could be use to ensure you are not delivering the inspector if not part of your final app.
 

+ 41 - 14
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -229,7 +229,7 @@ var EXT_lights_image_based = /** @class */ (function () {
                     babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["Matrix"].FromQuaternionToRef(rotation, babylonTexture.getReflectionTextureMatrix());
                 }
                 var sphericalHarmonics = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["SphericalHarmonics"].FromArray(light.irradianceCoefficients);
-                sphericalHarmonics.scale(light.intensity);
+                sphericalHarmonics.scaleInPlace(light.intensity);
                 sphericalHarmonics.convertIrradianceToLambertianRadiance();
                 var sphericalPolynomial = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["SphericalPolynomial"].FromHarmonics(sphericalHarmonics);
                 // Compute the lod generation scale to fit exactly to the number of levels available.
@@ -277,15 +277,11 @@ var KHR_draco_mesh_compression = /** @class */ (function () {
         this.name = NAME;
         /** Defines whether this extension is enabled. */
         this.enabled = babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"].DecoderAvailable;
-        this._dracoCompressionOwned = false;
         this._loader = loader;
     }
     /** @hidden */
     KHR_draco_mesh_compression.prototype.dispose = function () {
-        if (this.dracoCompression && this._dracoCompressionOwned) {
-            this.dracoCompression.dispose();
-            delete this.dracoCompression;
-        }
+        delete this.dracoCompression;
         delete this._loader;
     };
     /** @hidden */
@@ -325,11 +321,8 @@ var KHR_draco_mesh_compression = /** @class */ (function () {
             var bufferView = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__["ArrayItem"].Get(extensionContext, _this._loader.gltf.bufferViews, extension.bufferView);
             if (!bufferView._dracoBabylonGeometry) {
                 bufferView._dracoBabylonGeometry = _this._loader.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
-                    if (!_this.dracoCompression) {
-                        _this.dracoCompression = new babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"]();
-                        _this._dracoCompressionOwned = true;
-                    }
-                    return _this.dracoCompression.decodeMeshAsync(data, attributes).then(function (babylonVertexData) {
+                    var dracoCompression = _this.dracoCompression || babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"].Default;
+                    return dracoCompression.decodeMeshAsync(data, attributes).then(function (babylonVertexData) {
                         var babylonGeometry = new babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["Geometry"](babylonMesh.name, _this._loader.babylonScene);
                         babylonVertexData.applyToGeometry(babylonGeometry);
                         return babylonGeometry;
@@ -1939,8 +1932,22 @@ var GLTFLoader = /** @class */ (function () {
             return node._babylonTransformNode;
         });
     };
+    /**
+     * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+     * @param context The context when loading the asset
+     * @param name The mesh name when loading the asset
+     * @param node The glTF node when loading the asset
+     * @param mesh The glTF mesh when loading the asset
+     * @param primitive The glTF mesh primitive property
+     * @param assign A function called synchronously after parsing the glTF properties
+     * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+     */
     GLTFLoader.prototype._loadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) {
         var _this = this;
+        var extensionPromise = this._extensionsLoadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign);
+        if (extensionPromise) {
+            return extensionPromise;
+        }
         this.logOpen("" + context);
         var canInstance = (node.skin == undefined && !mesh.primitives[0].targets);
         var babylonAbstractMesh;
@@ -2316,8 +2323,19 @@ var GLTFLoader = /** @class */ (function () {
             return babylonAnimationGroup;
         });
     };
-    GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
+    /**
+     * @hidden Loads a glTF animation channel.
+     * @param context The context when loading the asset
+     * @param animationContext The context of the animation when loading the asset
+     * @param animation The glTF animation property
+     * @param channel The glTF animation channel property
+     * @param babylonAnimationGroup The babylon animation group property
+     * @param animationTargetOverride The babylon animation channel target override property. My be null.
+     * @returns A void promise when the channel load is complete
+     */
+    GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup, animationTargetOverride) {
         var _this = this;
+        if (animationTargetOverride === void 0) { animationTargetOverride = null; }
         if (channel.target.node == undefined) {
             return Promise.resolve();
         }
@@ -2451,8 +2469,14 @@ var GLTFLoader = /** @class */ (function () {
                 var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
                 var babylonAnimation = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__["Animation"](animationName, targetPath, 1, animationType);
                 babylonAnimation.setKeys(keys);
-                targetNode._babylonTransformNode.animations.push(babylonAnimation);
-                babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonTransformNode);
+                if (animationTargetOverride != null && animationTargetOverride.animations != null) {
+                    animationTargetOverride.animations.push(babylonAnimation);
+                    babylonAnimationGroup.addTargetedAnimation(babylonAnimation, animationTargetOverride);
+                }
+                else {
+                    targetNode._babylonTransformNode.animations.push(babylonAnimation);
+                    babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonTransformNode);
+                }
             }
         });
     };
@@ -3193,6 +3217,9 @@ var GLTFLoader = /** @class */ (function () {
     GLTFLoader.prototype._extensionsLoadVertexDataAsync = function (context, primitive, babylonMesh) {
         return this._applyExtensions(primitive, "loadVertexData", function (extension) { return extension._loadVertexDataAsync && extension._loadVertexDataAsync(context, primitive, babylonMesh); });
     };
+    GLTFLoader.prototype._extensionsLoadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) {
+        return this._applyExtensions(primitive, "loadMeshPrimitive", function (extension) { return extension._loadMeshPrimitiveAsync && extension._loadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign); });
+    };
     GLTFLoader.prototype._extensionsLoadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) {
         return this._applyExtensions(material, "loadMaterial", function (extension) { return extension._loadMaterialAsync && extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign); });
     };

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


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


+ 41 - 14
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2778,7 +2778,7 @@ var EXT_lights_image_based = /** @class */ (function () {
                     babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["Matrix"].FromQuaternionToRef(rotation, babylonTexture.getReflectionTextureMatrix());
                 }
                 var sphericalHarmonics = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["SphericalHarmonics"].FromArray(light.irradianceCoefficients);
-                sphericalHarmonics.scale(light.intensity);
+                sphericalHarmonics.scaleInPlace(light.intensity);
                 sphericalHarmonics.convertIrradianceToLambertianRadiance();
                 var sphericalPolynomial = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["SphericalPolynomial"].FromHarmonics(sphericalHarmonics);
                 // Compute the lod generation scale to fit exactly to the number of levels available.
@@ -2826,15 +2826,11 @@ var KHR_draco_mesh_compression = /** @class */ (function () {
         this.name = NAME;
         /** Defines whether this extension is enabled. */
         this.enabled = babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"].DecoderAvailable;
-        this._dracoCompressionOwned = false;
         this._loader = loader;
     }
     /** @hidden */
     KHR_draco_mesh_compression.prototype.dispose = function () {
-        if (this.dracoCompression && this._dracoCompressionOwned) {
-            this.dracoCompression.dispose();
-            delete this.dracoCompression;
-        }
+        delete this.dracoCompression;
         delete this._loader;
     };
     /** @hidden */
@@ -2874,11 +2870,8 @@ var KHR_draco_mesh_compression = /** @class */ (function () {
             var bufferView = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__["ArrayItem"].Get(extensionContext, _this._loader.gltf.bufferViews, extension.bufferView);
             if (!bufferView._dracoBabylonGeometry) {
                 bufferView._dracoBabylonGeometry = _this._loader.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
-                    if (!_this.dracoCompression) {
-                        _this.dracoCompression = new babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"]();
-                        _this._dracoCompressionOwned = true;
-                    }
-                    return _this.dracoCompression.decodeMeshAsync(data, attributes).then(function (babylonVertexData) {
+                    var dracoCompression = _this.dracoCompression || babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"].Default;
+                    return dracoCompression.decodeMeshAsync(data, attributes).then(function (babylonVertexData) {
                         var babylonGeometry = new babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["Geometry"](babylonMesh.name, _this._loader.babylonScene);
                         babylonVertexData.applyToGeometry(babylonGeometry);
                         return babylonGeometry;
@@ -4488,8 +4481,22 @@ var GLTFLoader = /** @class */ (function () {
             return node._babylonTransformNode;
         });
     };
+    /**
+     * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+     * @param context The context when loading the asset
+     * @param name The mesh name when loading the asset
+     * @param node The glTF node when loading the asset
+     * @param mesh The glTF mesh when loading the asset
+     * @param primitive The glTF mesh primitive property
+     * @param assign A function called synchronously after parsing the glTF properties
+     * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+     */
     GLTFLoader.prototype._loadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) {
         var _this = this;
+        var extensionPromise = this._extensionsLoadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign);
+        if (extensionPromise) {
+            return extensionPromise;
+        }
         this.logOpen("" + context);
         var canInstance = (node.skin == undefined && !mesh.primitives[0].targets);
         var babylonAbstractMesh;
@@ -4865,8 +4872,19 @@ var GLTFLoader = /** @class */ (function () {
             return babylonAnimationGroup;
         });
     };
-    GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
+    /**
+     * @hidden Loads a glTF animation channel.
+     * @param context The context when loading the asset
+     * @param animationContext The context of the animation when loading the asset
+     * @param animation The glTF animation property
+     * @param channel The glTF animation channel property
+     * @param babylonAnimationGroup The babylon animation group property
+     * @param animationTargetOverride The babylon animation channel target override property. My be null.
+     * @returns A void promise when the channel load is complete
+     */
+    GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup, animationTargetOverride) {
         var _this = this;
+        if (animationTargetOverride === void 0) { animationTargetOverride = null; }
         if (channel.target.node == undefined) {
             return Promise.resolve();
         }
@@ -5000,8 +5018,14 @@ var GLTFLoader = /** @class */ (function () {
                 var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
                 var babylonAnimation = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__["Animation"](animationName, targetPath, 1, animationType);
                 babylonAnimation.setKeys(keys);
-                targetNode._babylonTransformNode.animations.push(babylonAnimation);
-                babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonTransformNode);
+                if (animationTargetOverride != null && animationTargetOverride.animations != null) {
+                    animationTargetOverride.animations.push(babylonAnimation);
+                    babylonAnimationGroup.addTargetedAnimation(babylonAnimation, animationTargetOverride);
+                }
+                else {
+                    targetNode._babylonTransformNode.animations.push(babylonAnimation);
+                    babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonTransformNode);
+                }
             }
         });
     };
@@ -5742,6 +5766,9 @@ var GLTFLoader = /** @class */ (function () {
     GLTFLoader.prototype._extensionsLoadVertexDataAsync = function (context, primitive, babylonMesh) {
         return this._applyExtensions(primitive, "loadVertexData", function (extension) { return extension._loadVertexDataAsync && extension._loadVertexDataAsync(context, primitive, babylonMesh); });
     };
+    GLTFLoader.prototype._extensionsLoadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) {
+        return this._applyExtensions(primitive, "loadMeshPrimitive", function (extension) { return extension._loadMeshPrimitiveAsync && extension._loadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign); });
+    };
     GLTFLoader.prototype._extensionsLoadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) {
         return this._applyExtensions(material, "loadMaterial", function (extension) { return extension._loadMaterialAsync && extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign); });
     };

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


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


+ 12 - 2
dist/preview release/loaders/babylon.objFileLoader.js

@@ -373,7 +373,7 @@ var MTLFileLoader = /** @class */ (function () {
         else {
             url += value;
         }
-        return new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Texture"](url, scene);
+        return new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Texture"](url, scene, false, OBJFileLoader.INVERT_TEXTURE_Y);
     };
     return MTLFileLoader;
 }());
@@ -438,6 +438,8 @@ var OBJFileLoader = /** @class */ (function () {
                 ComputeNormals: OBJFileLoader.COMPUTE_NORMALS,
                 ImportVertexColors: OBJFileLoader.IMPORT_VERTEX_COLORS,
                 InvertY: OBJFileLoader.INVERT_Y,
+                InvertTextureY: OBJFileLoader.INVERT_TEXTURE_Y,
+                UVScaling: OBJFileLoader.UV_SCALING,
                 MaterialLoadingFailsSilently: OBJFileLoader.MATERIAL_LOADING_FAILS_SILENTLY,
                 OptimizeWithUV: OBJFileLoader.OPTIMIZE_WITH_UV,
                 SkipMaterials: OBJFileLoader.SKIP_MATERIALS
@@ -920,7 +922,7 @@ var OBJFileLoader = /** @class */ (function () {
                 //Value of result
                 // ["vt 0.1 0.2 0.3", "0.1", "0.2"]
                 //Add the Vector in the list of uvs
-                uvs.push(new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Vector2"](parseFloat(result[1]), parseFloat(result[2])));
+                uvs.push(new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Vector2"](parseFloat(result[1]) * OBJFileLoader.UV_SCALING.x, parseFloat(result[2]) * OBJFileLoader.UV_SCALING.y));
                 //Identify patterns of faces
                 //Face could be defined in different type of pattern
             }
@@ -1183,6 +1185,10 @@ var OBJFileLoader = /** @class */ (function () {
      */
     OBJFileLoader.INVERT_Y = false;
     /**
+     * Invert Y-Axis of referenced textures on load
+     */
+    OBJFileLoader.INVERT_TEXTURE_Y = true;
+    /**
      * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
      */
     OBJFileLoader.IMPORT_VERTEX_COLORS = false;
@@ -1191,6 +1197,10 @@ var OBJFileLoader = /** @class */ (function () {
      */
     OBJFileLoader.COMPUTE_NORMALS = false;
     /**
+     * Defines custom scaling of UV coordinates of loaded meshes.
+     */
+    OBJFileLoader.UV_SCALING = new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Vector2"](1, 1);
+    /**
      * Skip loading the materials even if defined in the OBJ file (materials are ignored).
      */
     OBJFileLoader.SKIP_MATERIALS = false;

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


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


+ 53 - 6
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -1180,6 +1180,17 @@ declare module BABYLON.GLTF2 {
          */
         _loadVertexDataAsync?(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>>;
         /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync?(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
+        /**
          * @hidden Define this method to modify the default behavior when loading materials. Load material creates the material and then loads material properties.
          * @param context The context when loading the asset
          * @param material The glTF material property
@@ -1219,7 +1230,7 @@ declare module BABYLON.GLTF2 {
          */
         loadAnimationAsync?(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>>;
         /**
-         * Define this method to modify the default behavior when loading skins.
+         * @hidden Define this method to modify the default behavior when loading skins.
          * @param context The context when loading the asset
          * @param node The glTF node property
          * @param skin The glTF skin property
@@ -1227,7 +1238,7 @@ declare module BABYLON.GLTF2 {
          */
         _loadSkinAsync?(context: string, node: INode, skin: ISkin): Nullable<Promise<void>>;
         /**
-         * Define this method to modify the default behavior when loading uris.
+         * @hidden Define this method to modify the default behavior when loading uris.
          * @param context The context when loading the asset
          * @param property The glTF property associated with the uri
          * @param uri The uri to load
@@ -1346,7 +1357,17 @@ declare module BABYLON.GLTF2 {
          */
         loadNodeAsync(context: string, node: INode, assign?: (babylonTransformNode: TransformNode) => void): Promise<TransformNode>;
         private _loadMeshAsync;
-        private _loadMeshPrimitiveAsync;
+        /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
         private _loadVertexDataAsync;
         private _createMorphTargets;
         private _loadMorphTargetsAsync;
@@ -1374,7 +1395,17 @@ declare module BABYLON.GLTF2 {
          * @returns A promise that resolves with the loaded Babylon animation group when the load is complete
          */
         loadAnimationAsync(context: string, animation: IAnimation): Promise<AnimationGroup>;
-        private _loadAnimationChannelAsync;
+        /**
+         * @hidden Loads a glTF animation channel.
+         * @param context The context when loading the asset
+         * @param animationContext The context of the animation when loading the asset
+         * @param animation The glTF animation property
+         * @param channel The glTF animation channel property
+         * @param babylonAnimationGroup The babylon animation group property
+         * @param animationTargetOverride The babylon animation channel target override property. My be null.
+         * @returns A void promise when the channel load is complete
+         */
+        _loadAnimationChannelAsync(context: string, animationContext: string, animation: IAnimation, channel: IAnimationChannel, babylonAnimationGroup: AnimationGroup, animationTargetOverride?: Nullable<IAnimatable>): Promise<void>;
         private _loadAnimationSamplerAsync;
         private _loadBufferAsync;
         /**
@@ -1474,6 +1505,7 @@ declare module BABYLON.GLTF2 {
         private _extensionsLoadNodeAsync;
         private _extensionsLoadCameraAsync;
         private _extensionsLoadVertexDataAsync;
+        private _extensionsLoadMeshPrimitiveAsync;
         private _extensionsLoadMaterialAsync;
         private _extensionsCreateMaterial;
         private _extensionsLoadMaterialPropertiesAsync;
@@ -1554,12 +1586,11 @@ declare module BABYLON.GLTF2.Loader.Extensions {
     export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
         /** The name of this extension. */
         readonly name: string;
-        /** The draco compression used to decode vertex data. */
+        /** The draco compression used to decode vertex data or DracoCompression.Default if not defined */
         dracoCompression?: DracoCompression;
         /** Defines whether this extension is enabled. */
         enabled: boolean;
         private _loader;
-        private _dracoCompressionOwned;
         /** @hidden */
         constructor(loader: GLTFLoader);
         /** @hidden */
@@ -1789,10 +1820,18 @@ declare module BABYLON {
          */
         OptimizeWithUV: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        UVScaling: Vector2;
+        /**
          * Invert model on y-axis (does a model scaling inversion)
          */
         InvertY: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        InvertTextureY: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         ImportVertexColors: boolean;
@@ -1823,6 +1862,10 @@ declare module BABYLON {
          */
         static INVERT_Y: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        static INVERT_TEXTURE_Y: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         static IMPORT_VERTEX_COLORS: boolean;
@@ -1831,6 +1874,10 @@ declare module BABYLON {
          */
         static COMPUTE_NORMALS: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        static UV_SCALING: Vector2;
+        /**
          * Skip loading the materials even if defined in the OBJ file (materials are ignored).
          */
         static SKIP_MATERIALS: boolean;

+ 53 - 16
dist/preview release/loaders/babylonjs.loaders.js

@@ -591,7 +591,7 @@ var MTLFileLoader = /** @class */ (function () {
         else {
             url += value;
         }
-        return new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Texture"](url, scene);
+        return new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Texture"](url, scene, false, OBJFileLoader.INVERT_TEXTURE_Y);
     };
     return MTLFileLoader;
 }());
@@ -656,6 +656,8 @@ var OBJFileLoader = /** @class */ (function () {
                 ComputeNormals: OBJFileLoader.COMPUTE_NORMALS,
                 ImportVertexColors: OBJFileLoader.IMPORT_VERTEX_COLORS,
                 InvertY: OBJFileLoader.INVERT_Y,
+                InvertTextureY: OBJFileLoader.INVERT_TEXTURE_Y,
+                UVScaling: OBJFileLoader.UV_SCALING,
                 MaterialLoadingFailsSilently: OBJFileLoader.MATERIAL_LOADING_FAILS_SILENTLY,
                 OptimizeWithUV: OBJFileLoader.OPTIMIZE_WITH_UV,
                 SkipMaterials: OBJFileLoader.SKIP_MATERIALS
@@ -1138,7 +1140,7 @@ var OBJFileLoader = /** @class */ (function () {
                 //Value of result
                 // ["vt 0.1 0.2 0.3", "0.1", "0.2"]
                 //Add the Vector in the list of uvs
-                uvs.push(new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Vector2"](parseFloat(result[1]), parseFloat(result[2])));
+                uvs.push(new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Vector2"](parseFloat(result[1]) * OBJFileLoader.UV_SCALING.x, parseFloat(result[2]) * OBJFileLoader.UV_SCALING.y));
                 //Identify patterns of faces
                 //Face could be defined in different type of pattern
             }
@@ -1401,6 +1403,10 @@ var OBJFileLoader = /** @class */ (function () {
      */
     OBJFileLoader.INVERT_Y = false;
     /**
+     * Invert Y-Axis of referenced textures on load
+     */
+    OBJFileLoader.INVERT_TEXTURE_Y = true;
+    /**
      * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
      */
     OBJFileLoader.IMPORT_VERTEX_COLORS = false;
@@ -1409,6 +1415,10 @@ var OBJFileLoader = /** @class */ (function () {
      */
     OBJFileLoader.COMPUTE_NORMALS = false;
     /**
+     * Defines custom scaling of UV coordinates of loaded meshes.
+     */
+    OBJFileLoader.UV_SCALING = new babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Vector2"](1, 1);
+    /**
      * Skip loading the materials even if defined in the OBJ file (materials are ignored).
      */
     OBJFileLoader.SKIP_MATERIALS = false;
@@ -4110,7 +4120,7 @@ var EXT_lights_image_based = /** @class */ (function () {
                     babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["Matrix"].FromQuaternionToRef(rotation, babylonTexture.getReflectionTextureMatrix());
                 }
                 var sphericalHarmonics = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["SphericalHarmonics"].FromArray(light.irradianceCoefficients);
-                sphericalHarmonics.scale(light.intensity);
+                sphericalHarmonics.scaleInPlace(light.intensity);
                 sphericalHarmonics.convertIrradianceToLambertianRadiance();
                 var sphericalPolynomial = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__["SphericalPolynomial"].FromHarmonics(sphericalHarmonics);
                 // Compute the lod generation scale to fit exactly to the number of levels available.
@@ -4158,15 +4168,11 @@ var KHR_draco_mesh_compression = /** @class */ (function () {
         this.name = NAME;
         /** Defines whether this extension is enabled. */
         this.enabled = babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"].DecoderAvailable;
-        this._dracoCompressionOwned = false;
         this._loader = loader;
     }
     /** @hidden */
     KHR_draco_mesh_compression.prototype.dispose = function () {
-        if (this.dracoCompression && this._dracoCompressionOwned) {
-            this.dracoCompression.dispose();
-            delete this.dracoCompression;
-        }
+        delete this.dracoCompression;
         delete this._loader;
     };
     /** @hidden */
@@ -4206,11 +4212,8 @@ var KHR_draco_mesh_compression = /** @class */ (function () {
             var bufferView = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__["ArrayItem"].Get(extensionContext, _this._loader.gltf.bufferViews, extension.bufferView);
             if (!bufferView._dracoBabylonGeometry) {
                 bufferView._dracoBabylonGeometry = _this._loader.loadBufferViewAsync("#/bufferViews/" + bufferView.index, bufferView).then(function (data) {
-                    if (!_this.dracoCompression) {
-                        _this.dracoCompression = new babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"]();
-                        _this._dracoCompressionOwned = true;
-                    }
-                    return _this.dracoCompression.decodeMeshAsync(data, attributes).then(function (babylonVertexData) {
+                    var dracoCompression = _this.dracoCompression || babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["DracoCompression"].Default;
+                    return dracoCompression.decodeMeshAsync(data, attributes).then(function (babylonVertexData) {
                         var babylonGeometry = new babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__["Geometry"](babylonMesh.name, _this._loader.babylonScene);
                         babylonVertexData.applyToGeometry(babylonGeometry);
                         return babylonGeometry;
@@ -5820,8 +5823,22 @@ var GLTFLoader = /** @class */ (function () {
             return node._babylonTransformNode;
         });
     };
+    /**
+     * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+     * @param context The context when loading the asset
+     * @param name The mesh name when loading the asset
+     * @param node The glTF node when loading the asset
+     * @param mesh The glTF mesh when loading the asset
+     * @param primitive The glTF mesh primitive property
+     * @param assign A function called synchronously after parsing the glTF properties
+     * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+     */
     GLTFLoader.prototype._loadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) {
         var _this = this;
+        var extensionPromise = this._extensionsLoadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign);
+        if (extensionPromise) {
+            return extensionPromise;
+        }
         this.logOpen("" + context);
         var canInstance = (node.skin == undefined && !mesh.primitives[0].targets);
         var babylonAbstractMesh;
@@ -6197,8 +6214,19 @@ var GLTFLoader = /** @class */ (function () {
             return babylonAnimationGroup;
         });
     };
-    GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup) {
+    /**
+     * @hidden Loads a glTF animation channel.
+     * @param context The context when loading the asset
+     * @param animationContext The context of the animation when loading the asset
+     * @param animation The glTF animation property
+     * @param channel The glTF animation channel property
+     * @param babylonAnimationGroup The babylon animation group property
+     * @param animationTargetOverride The babylon animation channel target override property. My be null.
+     * @returns A void promise when the channel load is complete
+     */
+    GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, babylonAnimationGroup, animationTargetOverride) {
         var _this = this;
+        if (animationTargetOverride === void 0) { animationTargetOverride = null; }
         if (channel.target.node == undefined) {
             return Promise.resolve();
         }
@@ -6332,8 +6360,14 @@ var GLTFLoader = /** @class */ (function () {
                 var animationName = babylonAnimationGroup.name + "_channel" + babylonAnimationGroup.targetedAnimations.length;
                 var babylonAnimation = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__["Animation"](animationName, targetPath, 1, animationType);
                 babylonAnimation.setKeys(keys);
-                targetNode._babylonTransformNode.animations.push(babylonAnimation);
-                babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonTransformNode);
+                if (animationTargetOverride != null && animationTargetOverride.animations != null) {
+                    animationTargetOverride.animations.push(babylonAnimation);
+                    babylonAnimationGroup.addTargetedAnimation(babylonAnimation, animationTargetOverride);
+                }
+                else {
+                    targetNode._babylonTransformNode.animations.push(babylonAnimation);
+                    babylonAnimationGroup.addTargetedAnimation(babylonAnimation, targetNode._babylonTransformNode);
+                }
             }
         });
     };
@@ -7074,6 +7108,9 @@ var GLTFLoader = /** @class */ (function () {
     GLTFLoader.prototype._extensionsLoadVertexDataAsync = function (context, primitive, babylonMesh) {
         return this._applyExtensions(primitive, "loadVertexData", function (extension) { return extension._loadVertexDataAsync && extension._loadVertexDataAsync(context, primitive, babylonMesh); });
     };
+    GLTFLoader.prototype._extensionsLoadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) {
+        return this._applyExtensions(primitive, "loadMeshPrimitive", function (extension) { return extension._loadMeshPrimitiveAsync && extension._loadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign); });
+    };
     GLTFLoader.prototype._extensionsLoadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) {
         return this._applyExtensions(material, "loadMaterial", function (extension) { return extension._loadMaterialAsync && extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign); });
     };

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


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


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

@@ -1202,8 +1202,9 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
     import { TransformNode } from "babylonjs/Meshes/transformNode";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
     import { Mesh } from "babylonjs/Meshes/mesh";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { IDisposable } from "babylonjs/scene";
-    import { IScene, INode, ISkin, ICamera, IMeshPrimitive, IMaterial, ITextureInfo, IAnimation } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
+    import { IScene, INode, IMesh, ISkin, ICamera, IMeshPrimitive, IMaterial, ITextureInfo, IAnimation } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension as IGLTFBaseLoaderExtension } from "babylonjs-loaders/glTF/glTFFileLoader";
     import { IProperty } from 'babylonjs-gltf2interface';
     /**
@@ -1249,6 +1250,17 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
          */
         _loadVertexDataAsync?(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>>;
         /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync?(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
+        /**
          * @hidden Define this method to modify the default behavior when loading materials. Load material creates the material and then loads material properties.
          * @param context The context when loading the asset
          * @param material The glTF material property
@@ -1288,7 +1300,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
          */
         loadAnimationAsync?(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>>;
         /**
-         * Define this method to modify the default behavior when loading skins.
+         * @hidden Define this method to modify the default behavior when loading skins.
          * @param context The context when loading the asset
          * @param node The glTF node property
          * @param skin The glTF skin property
@@ -1296,7 +1308,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
          */
         _loadSkinAsync?(context: string, node: INode, skin: ISkin): Nullable<Promise<void>>;
         /**
-         * Define this method to modify the default behavior when loading uris.
+         * @hidden Define this method to modify the default behavior when loading uris.
          * @param context The context when loading the asset
          * @param property The glTF property associated with the uri
          * @param uri The uri to load
@@ -1307,6 +1319,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
 }
 declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
     import { Nullable } from "babylonjs/types";
+    import { IAnimatable } from "babylonjs/Misc/tools";
     import { Camera } from "babylonjs/Cameras/camera";
     import { AnimationGroup } from "babylonjs/Animations/animationGroup";
     import { Skeleton } from "babylonjs/Bones/skeleton";
@@ -1319,7 +1332,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
     import { SceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
     import { IProperty } from "babylonjs-gltf2interface";
-    import { IGLTF, INode, IScene, ICamera, IAnimation, IBufferView, IMaterial, ITextureInfo, IImage, IArrayItem as IArrItem } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
+    import { IGLTF, INode, IScene, IMesh, ICamera, IAnimation, IAnimationChannel, IBufferView, IMaterial, ITextureInfo, IImage, IMeshPrimitive, IArrayItem as IArrItem } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
     import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData } from "babylonjs-loaders/glTF/glTFFileLoader";
     /**
@@ -1431,7 +1444,17 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
          */
         loadNodeAsync(context: string, node: INode, assign?: (babylonTransformNode: TransformNode) => void): Promise<TransformNode>;
         private _loadMeshAsync;
-        private _loadMeshPrimitiveAsync;
+        /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
         private _loadVertexDataAsync;
         private _createMorphTargets;
         private _loadMorphTargetsAsync;
@@ -1459,7 +1482,17 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
          * @returns A promise that resolves with the loaded Babylon animation group when the load is complete
          */
         loadAnimationAsync(context: string, animation: IAnimation): Promise<AnimationGroup>;
-        private _loadAnimationChannelAsync;
+        /**
+         * @hidden Loads a glTF animation channel.
+         * @param context The context when loading the asset
+         * @param animationContext The context of the animation when loading the asset
+         * @param animation The glTF animation property
+         * @param channel The glTF animation channel property
+         * @param babylonAnimationGroup The babylon animation group property
+         * @param animationTargetOverride The babylon animation channel target override property. My be null.
+         * @returns A void promise when the channel load is complete
+         */
+        _loadAnimationChannelAsync(context: string, animationContext: string, animation: IAnimation, channel: IAnimationChannel, babylonAnimationGroup: AnimationGroup, animationTargetOverride?: Nullable<IAnimatable>): Promise<void>;
         private _loadAnimationSamplerAsync;
         private _loadBufferAsync;
         /**
@@ -1559,6 +1592,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
         private _extensionsLoadNodeAsync;
         private _extensionsLoadCameraAsync;
         private _extensionsLoadVertexDataAsync;
+        private _extensionsLoadMeshPrimitiveAsync;
         private _extensionsLoadMaterialAsync;
         private _extensionsCreateMaterial;
         private _extensionsLoadMaterialPropertiesAsync;
@@ -1650,12 +1684,11 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_draco_mesh_compression
     export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
         /** The name of this extension. */
         readonly name: string;
-        /** The draco compression used to decode vertex data. */
+        /** The draco compression used to decode vertex data or DracoCompression.Default if not defined */
         dracoCompression?: DracoCompression;
         /** Defines whether this extension is enabled. */
         enabled: boolean;
         private _loader;
-        private _dracoCompressionOwned;
         /** @hidden */
         constructor(loader: GLTFLoader);
         /** @hidden */
@@ -1914,6 +1947,7 @@ declare module "babylonjs-loaders/glTF/index" {
     export { GLTF1, GLTF2 };
 }
 declare module "babylonjs-loaders/OBJ/objFileLoader" {
+    import { Vector2 } from "babylonjs/Maths/math";
     import { AnimationGroup } from "babylonjs/Animations/animationGroup";
     import { Skeleton } from "babylonjs/Bones/skeleton";
     import { IParticleSystem } from "babylonjs/Particles/IParticleSystem";
@@ -1962,10 +1996,18 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          */
         OptimizeWithUV: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        UVScaling: Vector2;
+        /**
          * Invert model on y-axis (does a model scaling inversion)
          */
         InvertY: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        InvertTextureY: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         ImportVertexColors: boolean;
@@ -1996,6 +2038,10 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          */
         static INVERT_Y: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        static INVERT_TEXTURE_Y: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         static IMPORT_VERTEX_COLORS: boolean;
@@ -2004,6 +2050,10 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          */
         static COMPUTE_NORMALS: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        static UV_SCALING: Vector2;
+        /**
          * Skip loading the materials even if defined in the OBJ file (materials are ignored).
          */
         static SKIP_MATERIALS: boolean;
@@ -3431,6 +3481,17 @@ declare module BABYLON.GLTF2 {
          */
         _loadVertexDataAsync?(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>>;
         /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync?(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
+        /**
          * @hidden Define this method to modify the default behavior when loading materials. Load material creates the material and then loads material properties.
          * @param context The context when loading the asset
          * @param material The glTF material property
@@ -3470,7 +3531,7 @@ declare module BABYLON.GLTF2 {
          */
         loadAnimationAsync?(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>>;
         /**
-         * Define this method to modify the default behavior when loading skins.
+         * @hidden Define this method to modify the default behavior when loading skins.
          * @param context The context when loading the asset
          * @param node The glTF node property
          * @param skin The glTF skin property
@@ -3478,7 +3539,7 @@ declare module BABYLON.GLTF2 {
          */
         _loadSkinAsync?(context: string, node: INode, skin: ISkin): Nullable<Promise<void>>;
         /**
-         * Define this method to modify the default behavior when loading uris.
+         * @hidden Define this method to modify the default behavior when loading uris.
          * @param context The context when loading the asset
          * @param property The glTF property associated with the uri
          * @param uri The uri to load
@@ -3597,7 +3658,17 @@ declare module BABYLON.GLTF2 {
          */
         loadNodeAsync(context: string, node: INode, assign?: (babylonTransformNode: TransformNode) => void): Promise<TransformNode>;
         private _loadMeshAsync;
-        private _loadMeshPrimitiveAsync;
+        /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
         private _loadVertexDataAsync;
         private _createMorphTargets;
         private _loadMorphTargetsAsync;
@@ -3625,7 +3696,17 @@ declare module BABYLON.GLTF2 {
          * @returns A promise that resolves with the loaded Babylon animation group when the load is complete
          */
         loadAnimationAsync(context: string, animation: IAnimation): Promise<AnimationGroup>;
-        private _loadAnimationChannelAsync;
+        /**
+         * @hidden Loads a glTF animation channel.
+         * @param context The context when loading the asset
+         * @param animationContext The context of the animation when loading the asset
+         * @param animation The glTF animation property
+         * @param channel The glTF animation channel property
+         * @param babylonAnimationGroup The babylon animation group property
+         * @param animationTargetOverride The babylon animation channel target override property. My be null.
+         * @returns A void promise when the channel load is complete
+         */
+        _loadAnimationChannelAsync(context: string, animationContext: string, animation: IAnimation, channel: IAnimationChannel, babylonAnimationGroup: AnimationGroup, animationTargetOverride?: Nullable<IAnimatable>): Promise<void>;
         private _loadAnimationSamplerAsync;
         private _loadBufferAsync;
         /**
@@ -3725,6 +3806,7 @@ declare module BABYLON.GLTF2 {
         private _extensionsLoadNodeAsync;
         private _extensionsLoadCameraAsync;
         private _extensionsLoadVertexDataAsync;
+        private _extensionsLoadMeshPrimitiveAsync;
         private _extensionsLoadMaterialAsync;
         private _extensionsCreateMaterial;
         private _extensionsLoadMaterialPropertiesAsync;
@@ -3805,12 +3887,11 @@ declare module BABYLON.GLTF2.Loader.Extensions {
     export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
         /** The name of this extension. */
         readonly name: string;
-        /** The draco compression used to decode vertex data. */
+        /** The draco compression used to decode vertex data or DracoCompression.Default if not defined */
         dracoCompression?: DracoCompression;
         /** Defines whether this extension is enabled. */
         enabled: boolean;
         private _loader;
-        private _dracoCompressionOwned;
         /** @hidden */
         constructor(loader: GLTFLoader);
         /** @hidden */
@@ -4040,10 +4121,18 @@ declare module BABYLON {
          */
         OptimizeWithUV: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        UVScaling: Vector2;
+        /**
          * Invert model on y-axis (does a model scaling inversion)
          */
         InvertY: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        InvertTextureY: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         ImportVertexColors: boolean;
@@ -4074,6 +4163,10 @@ declare module BABYLON {
          */
         static INVERT_Y: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        static INVERT_TEXTURE_Y: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         static IMPORT_VERTEX_COLORS: boolean;
@@ -4082,6 +4175,10 @@ declare module BABYLON {
          */
         static COMPUTE_NORMALS: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        static UV_SCALING: Vector2;
+        /**
          * Skip loading the materials even if defined in the OBJ file (materials are ignored).
          */
         static SKIP_MATERIALS: boolean;

+ 3 - 3
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": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "4.0.0-beta.3",
-        "babylonjs": "4.0.0-beta.3"
+        "babylonjs-gltf2interface": "4.0.0-rc.1",
+        "babylonjs": "4.0.0-rc.1"
     },
     "engines": {
         "node": "*"

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

@@ -693,6 +693,8 @@ var PBRCustomMaterial = /** @class */ (function (_super) {
             .replace('#define CUSTOM_FRAGMENT_UPDATE_ALBEDO', (this.CustomParts.Fragment_Custom_Albedo ? this.CustomParts.Fragment_Custom_Albedo : ""))
             .replace('#define CUSTOM_FRAGMENT_UPDATE_ALPHA', (this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
             .replace('#define CUSTOM_FRAGMENT_BEFORE_LIGHTS', (this.CustomParts.Fragment_Before_Lights ? this.CustomParts.Fragment_Before_Lights : ""))
+            .replace('#define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS', (this.CustomParts.Fragment_Custom_MetallicRoughness ? this.CustomParts.Fragment_Custom_MetallicRoughness : ""))
+            .replace('#define CUSTOM_FRAGMENT_UPDATE_MICROSURFACE', (this.CustomParts.Fragment_Custom_MicroSurface ? this.CustomParts.Fragment_Custom_MicroSurface : ""))
             .replace('#define CUSTOM_FRAGMENT_BEFORE_FOG', (this.CustomParts.Fragment_Before_Fog ? this.CustomParts.Fragment_Before_Fog : ""))
             .replace('#define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR', (this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : ""));
         this._isCreatedShader = true;
@@ -742,6 +744,14 @@ var PBRCustomMaterial = /** @class */ (function (_super) {
         this.CustomParts.Fragment_Before_Lights = shaderPart;
         return this;
     };
+    PBRCustomMaterial.prototype.Fragment_Custom_MetallicRoughness = function (shaderPart) {
+        this.CustomParts.Fragment_Custom_MetallicRoughness = shaderPart;
+        return this;
+    };
+    PBRCustomMaterial.prototype.Fragment_Custom_MicroSurface = function (shaderPart) {
+        this.CustomParts.Fragment_Custom_MicroSurface = shaderPart;
+        return this;
+    };
     PBRCustomMaterial.prototype.Fragment_Before_Fog = function (shaderPart) {
         this.CustomParts.Fragment_Before_Fog = shaderPart;
         return this;

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


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


+ 4 - 4
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js

@@ -548,16 +548,16 @@ var ShadowOnlyMaterial = /** @class */ (function (_super) {
         var engine = scene.getEngine();
         // Ensure that active light is the first shadow light
         if (this._activeLight) {
-            for (var _i = 0, _a = mesh._lightSources; _i < _a.length; _i++) {
+            for (var _i = 0, _a = mesh.lightSources; _i < _a.length; _i++) {
                 var light = _a[_i];
                 if (light.shadowEnabled) {
                     if (this._activeLight === light) {
                         break; // We are good
                     }
-                    var lightPosition = mesh._lightSources.indexOf(this._activeLight);
+                    var lightPosition = mesh.lightSources.indexOf(this._activeLight);
                     if (lightPosition !== -1) {
-                        mesh._lightSources.splice(lightPosition, 1);
-                        mesh._lightSources.splice(0, 0, this._activeLight);
+                        mesh.lightSources.splice(lightPosition, 1);
+                        mesh.lightSources.splice(0, 0, this._activeLight);
                     }
                     break;
                 }

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


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


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

@@ -103,6 +103,8 @@ declare module BABYLON {
         Fragment_MainBegin: string;
         Fragment_Custom_Albedo: string;
         Fragment_Before_Lights: string;
+        Fragment_Custom_MetallicRoughness: string;
+        Fragment_Custom_MicroSurface: string;
         Fragment_Before_Fog: string;
         Fragment_Custom_Alpha: string;
         Fragment_Before_FragColor: string;
@@ -135,6 +137,8 @@ declare module BABYLON {
         Fragment_Custom_Albedo(shaderPart: string): PBRCustomMaterial;
         Fragment_Custom_Alpha(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_Lights(shaderPart: string): PBRCustomMaterial;
+        Fragment_Custom_MetallicRoughness(shaderPart: string): PBRCustomMaterial;
+        Fragment_Custom_MicroSurface(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_Fog(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_FragColor(shaderPart: string): PBRCustomMaterial;
         Vertex_Begin(shaderPart: string): PBRCustomMaterial;

+ 14 - 4
dist/preview release/materialsLibrary/babylonjs.materials.js

@@ -1081,6 +1081,8 @@ var PBRCustomMaterial = /** @class */ (function (_super) {
             .replace('#define CUSTOM_FRAGMENT_UPDATE_ALBEDO', (this.CustomParts.Fragment_Custom_Albedo ? this.CustomParts.Fragment_Custom_Albedo : ""))
             .replace('#define CUSTOM_FRAGMENT_UPDATE_ALPHA', (this.CustomParts.Fragment_Custom_Alpha ? this.CustomParts.Fragment_Custom_Alpha : ""))
             .replace('#define CUSTOM_FRAGMENT_BEFORE_LIGHTS', (this.CustomParts.Fragment_Before_Lights ? this.CustomParts.Fragment_Before_Lights : ""))
+            .replace('#define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS', (this.CustomParts.Fragment_Custom_MetallicRoughness ? this.CustomParts.Fragment_Custom_MetallicRoughness : ""))
+            .replace('#define CUSTOM_FRAGMENT_UPDATE_MICROSURFACE', (this.CustomParts.Fragment_Custom_MicroSurface ? this.CustomParts.Fragment_Custom_MicroSurface : ""))
             .replace('#define CUSTOM_FRAGMENT_BEFORE_FOG', (this.CustomParts.Fragment_Before_Fog ? this.CustomParts.Fragment_Before_Fog : ""))
             .replace('#define CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR', (this.CustomParts.Fragment_Before_FragColor ? this.CustomParts.Fragment_Before_FragColor : ""));
         this._isCreatedShader = true;
@@ -1130,6 +1132,14 @@ var PBRCustomMaterial = /** @class */ (function (_super) {
         this.CustomParts.Fragment_Before_Lights = shaderPart;
         return this;
     };
+    PBRCustomMaterial.prototype.Fragment_Custom_MetallicRoughness = function (shaderPart) {
+        this.CustomParts.Fragment_Custom_MetallicRoughness = shaderPart;
+        return this;
+    };
+    PBRCustomMaterial.prototype.Fragment_Custom_MicroSurface = function (shaderPart) {
+        this.CustomParts.Fragment_Custom_MicroSurface = shaderPart;
+        return this;
+    };
     PBRCustomMaterial.prototype.Fragment_Before_Fog = function (shaderPart) {
         this.CustomParts.Fragment_Before_Fog = shaderPart;
         return this;
@@ -4649,16 +4659,16 @@ var ShadowOnlyMaterial = /** @class */ (function (_super) {
         var engine = scene.getEngine();
         // Ensure that active light is the first shadow light
         if (this._activeLight) {
-            for (var _i = 0, _a = mesh._lightSources; _i < _a.length; _i++) {
+            for (var _i = 0, _a = mesh.lightSources; _i < _a.length; _i++) {
                 var light = _a[_i];
                 if (light.shadowEnabled) {
                     if (this._activeLight === light) {
                         break; // We are good
                     }
-                    var lightPosition = mesh._lightSources.indexOf(this._activeLight);
+                    var lightPosition = mesh.lightSources.indexOf(this._activeLight);
                     if (lightPosition !== -1) {
-                        mesh._lightSources.splice(lightPosition, 1);
-                        mesh._lightSources.splice(0, 0, this._activeLight);
+                        mesh.lightSources.splice(lightPosition, 1);
+                        mesh.lightSources.splice(0, 0, this._activeLight);
                     }
                     break;
                 }

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


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


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

@@ -151,6 +151,8 @@ declare module "babylonjs-materials/custom/pbrCustomMaterial" {
         Fragment_MainBegin: string;
         Fragment_Custom_Albedo: string;
         Fragment_Before_Lights: string;
+        Fragment_Custom_MetallicRoughness: string;
+        Fragment_Custom_MicroSurface: string;
         Fragment_Before_Fog: string;
         Fragment_Custom_Alpha: string;
         Fragment_Before_FragColor: string;
@@ -183,6 +185,8 @@ declare module "babylonjs-materials/custom/pbrCustomMaterial" {
         Fragment_Custom_Albedo(shaderPart: string): PBRCustomMaterial;
         Fragment_Custom_Alpha(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_Lights(shaderPart: string): PBRCustomMaterial;
+        Fragment_Custom_MetallicRoughness(shaderPart: string): PBRCustomMaterial;
+        Fragment_Custom_MicroSurface(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_Fog(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_FragColor(shaderPart: string): PBRCustomMaterial;
         Vertex_Begin(shaderPart: string): PBRCustomMaterial;
@@ -1637,6 +1641,8 @@ declare module BABYLON {
         Fragment_MainBegin: string;
         Fragment_Custom_Albedo: string;
         Fragment_Before_Lights: string;
+        Fragment_Custom_MetallicRoughness: string;
+        Fragment_Custom_MicroSurface: string;
         Fragment_Before_Fog: string;
         Fragment_Custom_Alpha: string;
         Fragment_Before_FragColor: string;
@@ -1669,6 +1675,8 @@ declare module BABYLON {
         Fragment_Custom_Albedo(shaderPart: string): PBRCustomMaterial;
         Fragment_Custom_Alpha(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_Lights(shaderPart: string): PBRCustomMaterial;
+        Fragment_Custom_MetallicRoughness(shaderPart: string): PBRCustomMaterial;
+        Fragment_Custom_MicroSurface(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_Fog(shaderPart: string): PBRCustomMaterial;
         Fragment_Before_FragColor(shaderPart: string): PBRCustomMaterial;
         Vertex_Begin(shaderPart: string): PBRCustomMaterial;

+ 2 - 2
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": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-beta.3"
+        "babylonjs": "4.0.0-rc.1"
     },
     "engines": {
         "node": "*"

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

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

+ 1 - 1
dist/preview release/packagesSizeBaseLine.json

@@ -1 +1 @@
-{"engineOnly":307404,"sceneOnly":511832,"minGridMaterial":635906,"minStandardMaterial":759725}
+{"engineOnly":289856,"sceneOnly":499041,"minGridMaterial":625526,"minStandardMaterial":750285}

+ 2 - 2
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": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-beta.3"
+        "babylonjs": "4.0.0-rc.1"
     },
     "engines": {
         "node": "*"

+ 2 - 2
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": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-beta.3"
+        "babylonjs": "4.0.0-rc.1"
     },
     "engines": {
         "node": "*"

+ 1 - 1
dist/preview release/readme.md

@@ -3,7 +3,7 @@
 Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
 
 [![npm version](https://badge.fury.io/js/babylonjs.svg)](https://badge.fury.io/js/babylonjs)
-[![Build Status](https://travis-ci.com/BabylonJS/Babylon.js.svg?branch=master)](https://travis-ci.com/BabylonJS/Babylon.js)
+[![Build Status](https://dev.azure.com/babylonjs/ContinousIntegration/_apis/build/status/CI?branchName=master)](https://dev.azure.com/babylonjs/ContinousIntegration/_build/latest?definitionId=1&branchName=master)
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/BabylonJS/Babylon.js.svg)](http://isitmaintained.com/project/BabylonJS/Babylon.js "Average time to resolve an issue")
 [![Percentage of issues still open](https://isitmaintained.com/badge/open/babylonJS/babylon.js.svg)](https://isitmaintained.com/project/babylonJS/babylon.js "Percentage of issues still open")
 [![Build Size](https://img.badgesize.io/BabylonJS/Babylon.js/master/dist/preview%20release/babylon.js.svg?compression=gzip)](https://img.badgesize.io/BabylonJS/Babylon.js/master/dist/preview%20release/babylon.js.svg?compression=gzip)

+ 8 - 3
dist/preview release/serializers/babylon.glTF2Serializer.js

@@ -729,7 +729,12 @@ var _GLTFAnimation = /** @class */ (function () {
                     }
                     previousTime = time;
                     maxUsedFrame = time;
-                    value = animation._interpolate(f, 0, undefined, animation.loopMode);
+                    var state = {
+                        key: 0,
+                        repeatCount: 0,
+                        loopMode: animation.loopMode
+                    };
+                    value = animation._interpolate(f, state);
                     _GLTFAnimation._SetInterpolatedValue(babylonTransformNode, value, time, animation, animationChannelTargetPath, quaternionCache, inputs, outputs, convertToRightHandedSystem, useQuaternion);
                 }
             }
@@ -2160,8 +2165,8 @@ var _Exporter = /** @class */ (function () {
                     }
                     if (materialIndex != null && Object.keys(meshPrimitive.attributes).length > 0) {
                         var sideOrientation = babylonMaterial.sideOrientation;
-                        if (this._convertToRightHandedSystem && sideOrientation === babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Material"].ClockWiseSideOrientation) {
-                            //Overwrite the indices to be counter-clockwise
+                        // Only reverse the winding if we have a clockwise winding
+                        if (sideOrientation === babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Material"].ClockWiseSideOrientation) {
                             var byteOffset = indexBufferViewIndex != null ? this._bufferViews[indexBufferViewIndex].byteOffset : null;
                             if (byteOffset == null) {
                                 byteOffset = 0;

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


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


+ 8 - 3
dist/preview release/serializers/babylonjs.serializers.js

@@ -907,7 +907,12 @@ var _GLTFAnimation = /** @class */ (function () {
                     }
                     previousTime = time;
                     maxUsedFrame = time;
-                    value = animation._interpolate(f, 0, undefined, animation.loopMode);
+                    var state = {
+                        key: 0,
+                        repeatCount: 0,
+                        loopMode: animation.loopMode
+                    };
+                    value = animation._interpolate(f, state);
                     _GLTFAnimation._SetInterpolatedValue(babylonTransformNode, value, time, animation, animationChannelTargetPath, quaternionCache, inputs, outputs, convertToRightHandedSystem, useQuaternion);
                 }
             }
@@ -2338,8 +2343,8 @@ var _Exporter = /** @class */ (function () {
                     }
                     if (materialIndex != null && Object.keys(meshPrimitive.attributes).length > 0) {
                         var sideOrientation = babylonMaterial.sideOrientation;
-                        if (this._convertToRightHandedSystem && sideOrientation === babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Material"].ClockWiseSideOrientation) {
-                            //Overwrite the indices to be counter-clockwise
+                        // Only reverse the winding if we have a clockwise winding
+                        if (sideOrientation === babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__["Material"].ClockWiseSideOrientation) {
                             var byteOffset = indexBufferViewIndex != null ? this._bufferViews[indexBufferViewIndex].byteOffset : null;
                             if (byteOffset == null) {
                                 byteOffset = 0;

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


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


+ 3 - 3
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": "4.0.0-beta.3",
+    "version": "4.0.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-beta.3",
-        "babylonjs-gltf2interface": "4.0.0-beta.3"
+        "babylonjs": "4.0.0-rc.1",
+        "babylonjs-gltf2interface": "4.0.0-rc.1"
     },
     "engines": {
         "node": "*"

File diff suppressed because it is too large
+ 2471 - 1539
dist/preview release/viewer/babylon.module.d.ts


+ 15 - 1
dist/preview release/viewer/babylon.viewer.d.ts

@@ -951,7 +951,7 @@ declare module BabylonViewer {
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 declare module BabylonViewer {
@@ -1594,6 +1594,20 @@ declare module BabylonViewer {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 declare module BabylonViewer {
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+declare module BabylonViewer {
     export interface IEnvironmentMapConfiguration {
             /**
                 * Environment map texture path in relative to the asset folder.

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


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


+ 18 - 1
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -1031,13 +1031,14 @@ declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 }
 
 declare module 'babylonjs-viewer/optimizer/custom' {
+    import { extendedUpgrade } from "babylonjs-viewer/optimizer/custom/extended";
     import { SceneManager } from "babylonjs-viewer/managers/sceneManager";
     /**
       *
       * @param name the name of the custom optimizer configuration
       * @param upgrade set to true if you want to upgrade optimizer and false if you want to degrade
       */
-    export function getCustomOptimizerByName(name: string, upgrade?: boolean): (sceneManager: SceneManager) => boolean;
+    export function getCustomOptimizerByName(name: string, upgrade?: boolean): typeof extendedUpgrade;
     export function registerCustomOptimizer(name: string, optimizer: (sceneManager: SceneManager) => boolean): void;
 }
 
@@ -1737,6 +1738,22 @@ declare module 'babylonjs-viewer/loader/plugins' {
     export function addLoaderPlugin(name: string, plugin: ILoaderPlugin): void;
 }
 
+declare module 'babylonjs-viewer/optimizer/custom/extended' {
+    import { SceneManager } from 'babylonjs-viewer/managers/sceneManager';
+    /**
+        * A custom upgrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedUpgrade(sceneManager: SceneManager): boolean;
+    /**
+        * A custom degrade-oriented function configuration for the scene optimizer.
+        *
+        * @param viewer the viewer to optimize
+        */
+    export function extendedDegrade(sceneManager: SceneManager): boolean;
+}
+
 declare module 'babylonjs-viewer/configuration/interfaces' {
     export * from 'babylonjs-viewer/configuration/interfaces/cameraConfiguration';
     export * from 'babylonjs-viewer/configuration/interfaces/colorGradingConfiguration';

+ 111 - 14
dist/preview release/viewer/babylonjs.loaders.module.d.ts

@@ -1202,8 +1202,9 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
     import { TransformNode } from "babylonjs/Meshes/transformNode";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
     import { Mesh } from "babylonjs/Meshes/mesh";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { IDisposable } from "babylonjs/scene";
-    import { IScene, INode, ISkin, ICamera, IMeshPrimitive, IMaterial, ITextureInfo, IAnimation } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
+    import { IScene, INode, IMesh, ISkin, ICamera, IMeshPrimitive, IMaterial, ITextureInfo, IAnimation } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension as IGLTFBaseLoaderExtension } from "babylonjs-loaders/glTF/glTFFileLoader";
     import { IProperty } from 'babylonjs-gltf2interface';
     /**
@@ -1249,6 +1250,17 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
          */
         _loadVertexDataAsync?(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>>;
         /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync?(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
+        /**
          * @hidden Define this method to modify the default behavior when loading materials. Load material creates the material and then loads material properties.
          * @param context The context when loading the asset
          * @param material The glTF material property
@@ -1288,7 +1300,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
          */
         loadAnimationAsync?(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>>;
         /**
-         * Define this method to modify the default behavior when loading skins.
+         * @hidden Define this method to modify the default behavior when loading skins.
          * @param context The context when loading the asset
          * @param node The glTF node property
          * @param skin The glTF skin property
@@ -1296,7 +1308,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
          */
         _loadSkinAsync?(context: string, node: INode, skin: ISkin): Nullable<Promise<void>>;
         /**
-         * Define this method to modify the default behavior when loading uris.
+         * @hidden Define this method to modify the default behavior when loading uris.
          * @param context The context when loading the asset
          * @param property The glTF property associated with the uri
          * @param uri The uri to load
@@ -1307,6 +1319,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoaderExtension" {
 }
 declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
     import { Nullable } from "babylonjs/types";
+    import { IAnimatable } from "babylonjs/Misc/tools";
     import { Camera } from "babylonjs/Cameras/camera";
     import { AnimationGroup } from "babylonjs/Animations/animationGroup";
     import { Skeleton } from "babylonjs/Bones/skeleton";
@@ -1319,7 +1332,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
     import { SceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
     import { IProperty } from "babylonjs-gltf2interface";
-    import { IGLTF, INode, IScene, ICamera, IAnimation, IBufferView, IMaterial, ITextureInfo, IImage, IArrayItem as IArrItem } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
+    import { IGLTF, INode, IScene, IMesh, ICamera, IAnimation, IAnimationChannel, IBufferView, IMaterial, ITextureInfo, IImage, IMeshPrimitive, IArrayItem as IArrItem } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
     import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData } from "babylonjs-loaders/glTF/glTFFileLoader";
     /**
@@ -1431,7 +1444,17 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
          */
         loadNodeAsync(context: string, node: INode, assign?: (babylonTransformNode: TransformNode) => void): Promise<TransformNode>;
         private _loadMeshAsync;
-        private _loadMeshPrimitiveAsync;
+        /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
         private _loadVertexDataAsync;
         private _createMorphTargets;
         private _loadMorphTargetsAsync;
@@ -1459,7 +1482,17 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
          * @returns A promise that resolves with the loaded Babylon animation group when the load is complete
          */
         loadAnimationAsync(context: string, animation: IAnimation): Promise<AnimationGroup>;
-        private _loadAnimationChannelAsync;
+        /**
+         * @hidden Loads a glTF animation channel.
+         * @param context The context when loading the asset
+         * @param animationContext The context of the animation when loading the asset
+         * @param animation The glTF animation property
+         * @param channel The glTF animation channel property
+         * @param babylonAnimationGroup The babylon animation group property
+         * @param animationTargetOverride The babylon animation channel target override property. My be null.
+         * @returns A void promise when the channel load is complete
+         */
+        _loadAnimationChannelAsync(context: string, animationContext: string, animation: IAnimation, channel: IAnimationChannel, babylonAnimationGroup: AnimationGroup, animationTargetOverride?: Nullable<IAnimatable>): Promise<void>;
         private _loadAnimationSamplerAsync;
         private _loadBufferAsync;
         /**
@@ -1559,6 +1592,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
         private _extensionsLoadNodeAsync;
         private _extensionsLoadCameraAsync;
         private _extensionsLoadVertexDataAsync;
+        private _extensionsLoadMeshPrimitiveAsync;
         private _extensionsLoadMaterialAsync;
         private _extensionsCreateMaterial;
         private _extensionsLoadMaterialPropertiesAsync;
@@ -1650,12 +1684,11 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_draco_mesh_compression
     export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
         /** The name of this extension. */
         readonly name: string;
-        /** The draco compression used to decode vertex data. */
+        /** The draco compression used to decode vertex data or DracoCompression.Default if not defined */
         dracoCompression?: DracoCompression;
         /** Defines whether this extension is enabled. */
         enabled: boolean;
         private _loader;
-        private _dracoCompressionOwned;
         /** @hidden */
         constructor(loader: GLTFLoader);
         /** @hidden */
@@ -1914,6 +1947,7 @@ declare module "babylonjs-loaders/glTF/index" {
     export { GLTF1, GLTF2 };
 }
 declare module "babylonjs-loaders/OBJ/objFileLoader" {
+    import { Vector2 } from "babylonjs/Maths/math";
     import { AnimationGroup } from "babylonjs/Animations/animationGroup";
     import { Skeleton } from "babylonjs/Bones/skeleton";
     import { IParticleSystem } from "babylonjs/Particles/IParticleSystem";
@@ -1962,10 +1996,18 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          */
         OptimizeWithUV: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        UVScaling: Vector2;
+        /**
          * Invert model on y-axis (does a model scaling inversion)
          */
         InvertY: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        InvertTextureY: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         ImportVertexColors: boolean;
@@ -1996,6 +2038,10 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          */
         static INVERT_Y: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        static INVERT_TEXTURE_Y: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         static IMPORT_VERTEX_COLORS: boolean;
@@ -2004,6 +2050,10 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          */
         static COMPUTE_NORMALS: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        static UV_SCALING: Vector2;
+        /**
          * Skip loading the materials even if defined in the OBJ file (materials are ignored).
          */
         static SKIP_MATERIALS: boolean;
@@ -3431,6 +3481,17 @@ declare module BABYLON.GLTF2 {
          */
         _loadVertexDataAsync?(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>>;
         /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync?(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
+        /**
          * @hidden Define this method to modify the default behavior when loading materials. Load material creates the material and then loads material properties.
          * @param context The context when loading the asset
          * @param material The glTF material property
@@ -3470,7 +3531,7 @@ declare module BABYLON.GLTF2 {
          */
         loadAnimationAsync?(context: string, animation: IAnimation): Nullable<Promise<AnimationGroup>>;
         /**
-         * Define this method to modify the default behavior when loading skins.
+         * @hidden Define this method to modify the default behavior when loading skins.
          * @param context The context when loading the asset
          * @param node The glTF node property
          * @param skin The glTF skin property
@@ -3478,7 +3539,7 @@ declare module BABYLON.GLTF2 {
          */
         _loadSkinAsync?(context: string, node: INode, skin: ISkin): Nullable<Promise<void>>;
         /**
-         * Define this method to modify the default behavior when loading uris.
+         * @hidden Define this method to modify the default behavior when loading uris.
          * @param context The context when loading the asset
          * @param property The glTF property associated with the uri
          * @param uri The uri to load
@@ -3597,7 +3658,17 @@ declare module BABYLON.GLTF2 {
          */
         loadNodeAsync(context: string, node: INode, assign?: (babylonTransformNode: TransformNode) => void): Promise<TransformNode>;
         private _loadMeshAsync;
-        private _loadMeshPrimitiveAsync;
+        /**
+         * @hidden Define this method to modify the default behavior when loading data for mesh primitives.
+         * @param context The context when loading the asset
+         * @param name The mesh name when loading the asset
+         * @param node The glTF node when loading the asset
+         * @param mesh The glTF mesh when loading the asset
+         * @param primitive The glTF mesh primitive property
+         * @param assign A function called synchronously after parsing the glTF properties
+         * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled
+         */
+        _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Promise<AbstractMesh>;
         private _loadVertexDataAsync;
         private _createMorphTargets;
         private _loadMorphTargetsAsync;
@@ -3625,7 +3696,17 @@ declare module BABYLON.GLTF2 {
          * @returns A promise that resolves with the loaded Babylon animation group when the load is complete
          */
         loadAnimationAsync(context: string, animation: IAnimation): Promise<AnimationGroup>;
-        private _loadAnimationChannelAsync;
+        /**
+         * @hidden Loads a glTF animation channel.
+         * @param context The context when loading the asset
+         * @param animationContext The context of the animation when loading the asset
+         * @param animation The glTF animation property
+         * @param channel The glTF animation channel property
+         * @param babylonAnimationGroup The babylon animation group property
+         * @param animationTargetOverride The babylon animation channel target override property. My be null.
+         * @returns A void promise when the channel load is complete
+         */
+        _loadAnimationChannelAsync(context: string, animationContext: string, animation: IAnimation, channel: IAnimationChannel, babylonAnimationGroup: AnimationGroup, animationTargetOverride?: Nullable<IAnimatable>): Promise<void>;
         private _loadAnimationSamplerAsync;
         private _loadBufferAsync;
         /**
@@ -3725,6 +3806,7 @@ declare module BABYLON.GLTF2 {
         private _extensionsLoadNodeAsync;
         private _extensionsLoadCameraAsync;
         private _extensionsLoadVertexDataAsync;
+        private _extensionsLoadMeshPrimitiveAsync;
         private _extensionsLoadMaterialAsync;
         private _extensionsCreateMaterial;
         private _extensionsLoadMaterialPropertiesAsync;
@@ -3805,12 +3887,11 @@ declare module BABYLON.GLTF2.Loader.Extensions {
     export class KHR_draco_mesh_compression implements IGLTFLoaderExtension {
         /** The name of this extension. */
         readonly name: string;
-        /** The draco compression used to decode vertex data. */
+        /** The draco compression used to decode vertex data or DracoCompression.Default if not defined */
         dracoCompression?: DracoCompression;
         /** Defines whether this extension is enabled. */
         enabled: boolean;
         private _loader;
-        private _dracoCompressionOwned;
         /** @hidden */
         constructor(loader: GLTFLoader);
         /** @hidden */
@@ -4040,10 +4121,18 @@ declare module BABYLON {
          */
         OptimizeWithUV: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        UVScaling: Vector2;
+        /**
          * Invert model on y-axis (does a model scaling inversion)
          */
         InvertY: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        InvertTextureY: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         ImportVertexColors: boolean;
@@ -4074,6 +4163,10 @@ declare module BABYLON {
          */
         static INVERT_Y: boolean;
         /**
+         * Invert Y-Axis of referenced textures on load
+         */
+        static INVERT_TEXTURE_Y: boolean;
+        /**
          * Include in meshes the vertex colors available in some OBJ files.  This is not part of OBJ standard.
          */
         static IMPORT_VERTEX_COLORS: boolean;
@@ -4082,6 +4175,10 @@ declare module BABYLON {
          */
         static COMPUTE_NORMALS: boolean;
         /**
+         * Defines custom scaling of UV coordinates of loaded meshes.
+         */
+        static UV_SCALING: Vector2;
+        /**
          * Skip loading the materials even if defined in the OBJ file (materials are ignored).
          */
         static SKIP_MATERIALS: boolean;

+ 25 - 15
dist/preview release/what's new.md

@@ -8,7 +8,7 @@
 - Added [support for AmmoJS](https://doc.babylonjs.com/how_to/using_the_physics_engine) as a physics plugin (Composite objects, motors, joints) ([TrevorDev](https://github.com/TrevorDev))
   - Added support for soft bodies, which are 3D softbody, 2D cloth and 1D rope, in Ammo physics plugin. [Doc](https://doc.babylonjs.com/how_to/soft_bodies) ([JohnK](https://github.com/BabylonJSGuide))
   - Added support for [Convex Hull Impostor][https://github.com/kripken/ammo.js/blob/master/bullet/src/BulletCollision/CollisionShapes/btConvexHullShape.h] using Ammo.js plugin ([MackeyK24](https://github.com/mackeyk24))
-  - Added AmmoJSPlugin scene file loader [MackeyK24](https://github.com/mackeyk24))
+  - Added AmmoJSPlugin scene file loader ([MackeyK24](https://github.com/mackeyk24))
 - Added support for [WebXR](https://doc.babylonjs.com/how_to/webxr) ([TrevorDev](https://github.com/TrevorDev))
   - Add customAnimationFrameRequester to allow sessions to hook into engine's render loop ([TrevorDev](https://github.com/TrevorDev))
   - camera customDefaultRenderTarget to allow cameras to render to a custom render target (eg. xr framebuffer) instead of the canvas ([TrevorDev](https://github.com/TrevorDev))
@@ -30,13 +30,14 @@
 - Added `TrailMesh` class. Credit to furcatomasz ([danjpar](https://github.com/danjpar)) **** NEED DEMO or DOC LINK)
 - Support rendering to a Multiview outputRenderTargetTexture with multiview engine component to improve performance for XR scenarios ([TrevorDev](https://github.com/TrevorDev))
 - PBR:
-  - Added Inspector Debug Mode ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
-  - Added Smith Height Correlated Visibility term to PBR ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
-  - Added energy conservation through Multiscattering BRDF support to PBR ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
-  - Added clear coat support to PBR ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
-  - Added anisotropy support to PBR ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
-  - Added sheen support to PBR ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
-  - Added sub-surface support to PBR ([Sebavan](https://github.com/Sebavan)) **** NEED DEMO or DOC LINK)
+  - Added clear coat support to PBR ([Sebavan](https://github.com/Sebavan)) [Documentation](https://doc.babylonjs.com/how_to/physically_based_rendering_master#clear-coat)
+  - Added anisotropy support to PBR [Documentation](https://doc.babylonjs.com/how_to/physically_based_rendering_master#anisotropy)
+  - Added sheen support to PBR ([Sebavan](https://github.com/Sebavan)) [Documentation](https://doc.babylonjs.com/how_to/physically_based_rendering_master#sheen)
+  - Added sub-surface support to PBR ([Sebavan](https://github.com/Sebavan)) [Documentation](https://doc.babylonjs.com/how_to/physically_based_rendering_master#sub-surface)
+  - Added energy conservation through Multiscattering BRDF support to PBR [Documentation](https://doc.babylonjs.com/how_to/physically_based_rendering_master#energy-conservation)
+  - Added Inspector Debug Mode ([Sebavan](https://github.com/Sebavan)) [Documentation](https://doc.babylonjs.com/how_to/physically_based_rendering_master#how-to-debug)
+  - Added Smith Height Correlated Visibility term to PBR ([Sebavan](https://github.com/Sebavan)) [White Paper](http://jcgt.org/published/0003/02/03/)
+  - Added SH Harmonics support to PBR ([Sebavan](https://github.com/Sebavan)) [Documentation](https://doc.babylonjs.com/how_to/physically_based_rendering_master#spherical-harmonics)
 - Added a STL exporter ([pryme8](https://github.com/pryme8))
 
 ## Optimizations
@@ -79,6 +80,7 @@
 
 ### Core Engine
 
+- Add `reflectionMatrix` support for more `coordinatesMode`'s ([Dennis Dervisis](https://github.com/ddervisis))
 - Added new `WebRequest` class to centralize all network requests. Can be used to configure headers of all network requests ([Deltakosh](https://github.com/deltakosh))
 - Added `WebRequest.CustomRequestHeaders`, `WebRequest.UseCustomRequestHeaders` to send Custom Request Headers alongside XMLHttpRequest's i.e. when loading files (Tools.Loadfile) from resources requiring special headers like 'Authorization' ([susares](https://github.com/susares))
 - Added support for user clip planes to LineMeshes ([Deltakosh](https://github.com/deltakosh))
@@ -131,16 +133,18 @@
 - Added `MeshExploder` class ([danjpar](https://github.com/danjpar))
 - Observables can now make observers top or bottom priority ([TrevorDev](https://github.com/TrevorDev))
 - Mesh outline no longer is shown through the mesh when it's transparent ([TrevorDev](https://github.com/TrevorDev))
-- DeviceOrientationCamera will no longer be modified by mouse input if the orientation sensor is active ([TrevorDev](https://github.com/TrevorDev))
+- DeviceOrientationCamera will no longer be modified by mouse input when the orientation sensor is active ([TrevorDev](https://github.com/TrevorDev))
 - Added LoadScriptAsync tools helper function [MackeyK24](https://github.com/mackeyk24))
 - Added customShaderNameResolve to PBRMaterialBase to allow subclasses to specify custom shader information [MackeyK24](https://github.com/mackeyk24))
 - Added PBRCustomMaterial to material library to allow easy subclassing of PBR materials [MackeyK24](https://github.com/mackeyk24))
+- Added custom defines for roughness and microsurface in PBRCustomMaterial [Lockphase](https://github.com/lockphase)) 
 - Added `auto-exposure` support in `StandardRenderingPipeline` when `HDR` is enabled ([julien-moreau](https://github.com/julien-moreau))
 - Add `EquiRectangularCubeTexture` class to enable the usage of browser-canvas supported images as `CubeTexture`'s ([Dennis Dervisis](https://github.com/ddervisis))
 - Add `EquiRectangularCubeTextureAssetTask` to be able to load `EquiRectangularCubeTextures`s via Asset Manager ([Dennis Dervisis](https://github.com/ddervisis))
 - Added `Matrix.RotationAlignToRef` method to obtain rotation matrix from one vector to another ([sable](https://github.com/thscott))
 - ArcRotateCamera will now cache the necessary matrices when modifying its upVector, instead of calculating them each time they're needed ([sable](https://github.com/thscott))
 - Update `DracoCompression` to use web workers ([bghgary](https://github.com/bghgary))
+- Added `LOD Babylon Mesh Entities` to support to babylonFileLoader.ts ([MackeyK24](https://github.com/mackeyk24))
 
 ### OBJ Loader
 - Add color vertex support (not part of standard) ([brianzinn](https://github.com/brianzinn))
@@ -157,10 +161,13 @@
   - Skinned meshes now set an override mesh instead of reparenting to the `__root__` transform node
   - Loaded bones are linked with the transform node created for the corresponding glTF node
 - Improve load performance by blocking material dirtying during load ([bghgary](https://github.com/bghgary))
+- Added animation group target override to support custom animation targets ([MackeyK24](https://github.com/mackeyk24))
+- Added loadMeshPrimitiveAsync extension support ([MackeyK24](https://github.com/mackeyk24))
 
 ### glTF Serializer
 
 - Added support for exporting `KHR_lights_punctual`
+- Exporting a glTF from a Babylon scene with right-handed coordinate system should no longer cause the mesh normals to flip.([Nicholas Barlow](https://github.com/drigax))
 
 ### Post-Processes Library
 - Added the [Ocean](https://doc.babylonjs.com/extensions/oceanpostprocess) post-process ([julien-moreau](https://github.com/julien-moreau))
@@ -177,8 +184,6 @@
 - Migrating CI to Azure DevOps pipelines ([Sebavan](https://github.com/Sebavan))
 - Test both WebGL1 and WebGL2 ([Sebavan](https://github.com/Sebavan))
 
-### Viewer
-
 ## Bug fixes
 - Fixed ArcRotateCamera.setTarget (position was sometimes wrong) ([Deltakosh](https://github.com/deltakosh))
 - Fixed TransformNode.setDirection (orientation was wrong) ([Deltakosh](https://github.com/deltakosh))
@@ -191,7 +196,7 @@
 - Context loss causing unexpected results with dynamic textures, geometries with the same name and reflectionTextures ([TrevorDev](https://github.com/TrevorDev))
 - CreateScreenshotUsingRenderTarget stretches mirror textures when setting both width and height ([TrevorDev](https://github.com/TrevorDev))
 - VR helper only updating vr cameras position when entering vr, rotation was missing, laser distance stopped working ([TrevorDev](https://github.com/TrevorDev))
-- Fix VR controllers after gltfLoader transformNode change ([TrevorDev](https://github.com/TrevorDev))
+- Fix VR controllers after gltfLoader transformNode was changed ([TrevorDev](https://github.com/TrevorDev))
 - Bounding Box fixedDragMeshScreenSize stopped working and allow rotating through bounding box ([TrevorDev](https://github.com/TrevorDev))
 - VR helper would rotate non vr camera while in VR ([TrevorDev](https://github.com/TrevorDev))
 - PointerDragBahavior using Mesh as base type, causing type-checking problems with AbstractMesh ([Poolminer](https://github.com/Poolminer/))
@@ -210,7 +215,7 @@
 - CannonJS ignores connectedPivot joint parameter ([TrevorDev](https://github.com/TrevorDev))
 - Fix case sensitive paths ([mrdunk](https://github.com))
 - Fix more case sensitive paths ([mrdunk](https://github.com))
-- Attaching a BoundingBoxGizmo on a child should not remove its parent ([TrevorDev](https://github.com/TrevorDev))
+- Attaching a BoundingBoxGizmo on a child node shouldn't remove its parent, rotation gizmo should work on object with parent ([TrevorDev](https://github.com/TrevorDev))
 - AmmoJS fix include issue caused after modules update and use world contact point to be consistent with Oimo and Cannon ([TrevorDev](https://github.com/TrevorDev))
 - Warn of motor with maxForce in Oimo plugin and set default force to be consistent with others, cannonJS support no impostor, cannonJS cylinder axis, ammoJS wake up impostor when apply force/impulse ([TrevorDev](https://github.com/TrevorDev))
 - Utility layer should render on last active camera ([TrevorDev](https://github.com/TrevorDev))
@@ -228,6 +233,9 @@
 - Fix ArcRotateCamera rebuildAnglesAndRadius when upVector modified ([sable](https://github.com/thscott))
 - Fix code branch, that does not try to (re)load an `EquiRectangularCubeTexture`/`HDRCubeTexture` when the caching returns an empty or corrupt `InternalTexture` ([Dennis Dervisis](https://github.com/ddervisis))
 - Add error eventlistener (bubbling up the onError callback chain) in case an `EquiRectangularCubeTexture` cannot be loaded, because of a wrong path or IO problems ([Dennis Dervisis](https://github.com/ddervisis))
+- 3D GUI buttons no longer will scale up when pressing with a multitouch device ([TrevorDev](https://github.com/TrevorDev))
+- 2D GUI elements will use the last clicked controller instead of only the right controller when dual VR controllers are interacting with an element ([TrevorDev](https://github.com/TrevorDev))
+- Virtual keyboard not showing up when made visible ([TrevorDev](https://github.com/TrevorDev))
 
 ### Core Engine
 - Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))
@@ -253,12 +261,14 @@
 - Auto Update Touch Action [#5674](https://github.com/BabylonJS/Babylon.js/issues/5674)([Sebavan](https://github.com/Sebavan))
 - Add hemispheric lighting to gizmos to avoid flat look ([TrevorDev](https://github.com/TrevorDev))
 - Fix a bug causing `WebRequest.open` to crash if `WebRequest.CustomRequestHeaders` are set [#6055](https://github.com/BabylonJS/Babylon.js/issues/6055)([susares](https://github.com/susares))
-
-### Viewer
+- Fix a bug causing `Mesh.clone` to crash if no physicsEngineComponent is used  ([barroij](https://github.com/barroij))
+- Fix zoom inertia making it difficult to zoom out with ArcRotateCamera ([TrevorDev](https://github.com/TrevorDev))
+- Option for isInFrustum to check rigCameras, viewMatrix updates for rigCameras will notify their parent ([TrevorDev](https://github.com/TrevorDev))
 
 ### Loaders
 
 - Added missing `loadedAnimationGroups` to `MeshAssetTask` ([bghgary](https://github.com/bghgary))
+- Added missing `linkTransformNode` to `BabylonFileLoader` ([MackeyK24](https://github.com/mackeyk24))
 
 ## Breaking changes
 

+ 1 - 1
gui/src/2D/advancedDynamicTexture.ts

@@ -515,7 +515,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
                     });
                     continue;
                 }
-                var position = mesh.getBoundingInfo().boundingSphere.center;
+                var position = mesh.getBoundingInfo ? mesh.getBoundingInfo().boundingSphere.center : mesh.getAbsolutePosition();
                 var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
                 if (projectedPosition.z < 0 || projectedPosition.z > 1) {
                     control.notRenderable = true;

+ 9 - 3
gui/src/2D/controls/colorpicker.ts

@@ -29,6 +29,8 @@ export class ColorPicker extends Control {
     private _s = 1;
     private _v = 1;
 
+    private _lastPointerDownID = -1;
+
     /**
      * Observable raised when the value changes
      */
@@ -469,11 +471,15 @@ export class ColorPicker extends Control {
 
         this._updateValueFromPointer(x, y);
         this._host._capturingControl[pointerId] = this;
-
+        this._lastPointerDownID = pointerId;
         return true;
     }
 
-    public _onPointerMove(target: Control, coordinates: Vector2): void {
+    public _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void {
+        // Only listen to pointer move events coming from the last pointer to click on the element (To support dual vr controller interaction)
+        if (pointerId != this._lastPointerDownID) {
+            return;
+        }
         // Invert transform
         this._invertTransformMatrix.transformCoordinates(coordinates.x, coordinates.y, this._transformedPosition);
 
@@ -484,7 +490,7 @@ export class ColorPicker extends Control {
             this._updateValueFromPointer(x, y);
         }
 
-        super._onPointerMove(target, coordinates);
+        super._onPointerMove(target, coordinates, pointerId);
     }
 
     public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {

+ 3 - 3
gui/src/2D/controls/control.ts

@@ -1601,10 +1601,10 @@ export class Control {
     }
 
     /** @hidden */
-    public _onPointerMove(target: Control, coordinates: Vector2): void {
+    public _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void {
         var canNotify: boolean = this.onPointerMoveObservable.notifyObservers(coordinates, -1, target, this);
 
-        if (canNotify && this.parent != null) { this.parent._onPointerMove(target, coordinates); }
+        if (canNotify && this.parent != null) { this.parent._onPointerMove(target, coordinates, pointerId); }
     }
 
     /** @hidden */
@@ -1703,7 +1703,7 @@ export class Control {
         }
         this._dummyVector2.copyFromFloats(x, y);
         if (type === PointerEventTypes.POINTERMOVE) {
-            this._onPointerMove(this, this._dummyVector2);
+            this._onPointerMove(this, this._dummyVector2, pointerId);
 
             var previousControlOver = this._host._lastControlOver[pointerId];
             if (previousControlOver && previousControlOver !== this) {

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

@@ -993,13 +993,13 @@ export class InputText extends Control implements IFocusableControl {
 
         return true;
     }
-    public _onPointerMove(target: Control, coordinates: Vector2): void {
+    public _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void {
         if (this._host.focusedControl === this && this._isPointerDown) {
             this._clickedCoordinate = coordinates.x;
             this._markAsDirty();
             this._updateValueFromCursorIndex(this._cursorOffset);
         }
-        super._onPointerMove(target, coordinates);
+        super._onPointerMove(target, coordinates, pointerId);
     }
 
     public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {

+ 10 - 3
gui/src/2D/controls/sliders/baseSlider.ts

@@ -18,6 +18,8 @@ export class BaseSlider extends Control {
     protected _displayThumb = true;
     private _step = 0;
 
+    private _lastPointerDownID = -1;
+
     // Shared rendering info
     protected _effectiveBarOffset = 0;
     protected _renderLeft: number;
@@ -301,16 +303,21 @@ export class BaseSlider extends Control {
 
         this._updateValueFromPointer(coordinates.x, coordinates.y);
         this._host._capturingControl[pointerId] = this;
-
+        this._lastPointerDownID = pointerId;
         return true;
     }
 
-    public _onPointerMove(target: Control, coordinates: Vector2): void {
+    public _onPointerMove(target: Control, coordinates: Vector2, pointerId: number): void {
+        // Only listen to pointer move events coming from the last pointer to click on the element (To support dual vr controller interaction)
+        if (pointerId != this._lastPointerDownID) {
+            return;
+        }
+
         if (this._pointerIsDown) {
             this._updateValueFromPointer(coordinates.x, coordinates.y);
         }
 
-        super._onPointerMove(target, coordinates);
+        super._onPointerMove(target, coordinates, pointerId);
     }
 
     public _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void {

+ 9 - 1
gui/src/2D/controls/virtualKeyboard.ts

@@ -110,6 +110,7 @@ export class VirtualKeyboard extends StackPanel {
         panel.isVertical = false;
         panel.isFocusInvisible = true;
 
+        var maxKey: Nullable<Button> = null;
         for (var i = 0; i < keys.length; i++) {
             let properties = null;
 
@@ -117,9 +118,16 @@ export class VirtualKeyboard extends StackPanel {
                 properties = propertySets[i];
             }
 
-            panel.addControl(this._createKey(keys[i], properties));
+            var key = this._createKey(keys[i], properties);
+            if (!maxKey || key.heightInPixels > maxKey.heightInPixels) {
+                maxKey = key;
+            }
+
+            panel.addControl(key);
         }
 
+        panel.height = maxKey ? maxKey.height : this.defaultButtonHeight;
+
         this.addControl(panel);
     }
 

+ 20 - 7
gui/src/3D/controls/control3D.ts

@@ -333,6 +333,7 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
     /** @hidden */
     public _onPointerDown(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number): boolean {
         if (this._downCount !== 0) {
+            this._downCount++;
             return false;
         }
 
@@ -351,17 +352,24 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
 
     /** @hidden */
     public _onPointerUp(target: Control3D, coordinates: Vector3, pointerId: number, buttonIndex: number, notifyClick: boolean): void {
-        this._downCount = 0;
-
+        this._downCount--;
         delete this._downPointerIds[pointerId];
 
-        if (notifyClick && (this._enterCount > 0 || this._enterCount === -1)) {
-            this.onPointerClickObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
+        if (this._downCount < 0) {
+            // Handle if forcePointerUp was called prior to this
+            this._downCount = 0;
+            return;
         }
-        this.onPointerUpObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
 
-        if (this.pointerUpAnimation) {
-            this.pointerUpAnimation();
+        if (this._downCount == 0) {
+            if (notifyClick && (this._enterCount > 0 || this._enterCount === -1)) {
+                this.onPointerClickObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
+            }
+            this.onPointerUpObservable.notifyObservers(new Vector3WithInfo(coordinates, buttonIndex), -1, target, this);
+
+            if (this.pointerUpAnimation) {
+                this.pointerUpAnimation();
+            }
         }
     }
 
@@ -373,6 +381,11 @@ export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
             for (var key in this._downPointerIds) {
                 this._onPointerUp(this, Vector3.Zero(), +key as number, 0, true);
             }
+            if (this._downCount > 0) {
+                this._downCount = 1;
+                this._onPointerUp(this, Vector3.Zero(), 0, 0, true);
+            }
+
         }
     }
 

+ 2 - 2
inspector/src/components/actionTabs/lines/checkBoxLineComponent.tsx

@@ -24,7 +24,7 @@ export class CheckBoxLineComponent extends React.Component<ICheckBoxLineComponen
         if (this.props.isSelected) {
             this.state = { isSelected: this.props.isSelected() };
         } else {
-            this.state = { isSelected: this.props.target[this.props.propertyName!] };
+            this.state = { isSelected: this.props.target[this.props.propertyName!] === true };
         }
     }
 
@@ -34,7 +34,7 @@ export class CheckBoxLineComponent extends React.Component<ICheckBoxLineComponen
         if (this.props.isSelected) {
             currentState = nextProps.isSelected!();
         } else {
-            currentState = nextProps.target[nextProps.propertyName!];
+            currentState = nextProps.target[nextProps.propertyName!] === true;
         }
 
         if (currentState !== nextState.isSelected || this._localChange) {

+ 8 - 2
inspector/src/components/actionTabs/lines/vector2LineComponent.tsx

@@ -11,11 +11,17 @@ interface IVector2LineComponentProps {
     label: string;
     target: any;
     propertyName: string;
+    step?: number;
     onChange?: (newvalue: Vector2) => void;
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
 }
 
 export class Vector2LineComponent extends React.Component<IVector2LineComponentProps, { isExpanded: boolean, value: Vector2 }> {
+
+    static defaultProps = {
+        step: 0.001, // cm
+    };
+
     private _localChange = false;
 
     constructor(props: IVector2LineComponentProps) {
@@ -98,8 +104,8 @@ export class Vector2LineComponent extends React.Component<IVector2LineComponentP
                 {
                     this.state.isExpanded &&
                     <div className="secondLine">
-                        <NumericInputComponent label="x" value={this.state.value.x} onChange={value => this.updateStateX(value)} />
-                        <NumericInputComponent label="y" value={this.state.value.y} onChange={value => this.updateStateY(value)} />
+                        <NumericInputComponent label="x" step={this.props.step} value={this.state.value.x} onChange={value => this.updateStateX(value)} />
+                        <NumericInputComponent label="y" step={this.props.step} value={this.state.value.y} onChange={value => this.updateStateY(value)} />
                     </div>
                 }
             </div>

+ 1 - 1
inspector/src/components/actionTabs/lines/vector3LineComponent.tsx

@@ -19,7 +19,7 @@ interface IVector3LineComponentProps {
 export class Vector3LineComponent extends React.Component<IVector3LineComponentProps, { isExpanded: boolean, value: Vector3 }> {
 
     static defaultProps = {
-        step: 1,
+        step: 0.001, // cm
     };
 
     private _localChange = false;

+ 3 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/animationPropertyGridComponent.tsx

@@ -52,7 +52,9 @@ export class AnimationGridComponent extends React.Component<IAnimationGridCompon
             this._animations = new Array<Animation>();
 
             animatables.forEach((animatable: IAnimatable) => {
-                this._animations!.push(...animatable.animations);
+                if (animatable.animations) {
+                    this._animations!.push(...animatable.animations);
+                }
             });
 
             // Extract from and to

+ 3 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx

@@ -259,6 +259,9 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                     <CheckBoxLineComponent label="Energy Conservation" target={material.brdf} propertyName="useEnergyConservation"
                         onValueChanged={() => this.forceUpdate()}
                         onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Spherical Harmonics" target={material.brdf} propertyName="useSphericalHarmonics"
+                        onValueChanged={() => this.forceUpdate()}
+                        onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Radiance occlusion" target={material} propertyName="useRadianceOcclusion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Horizon occlusion " target={material} propertyName="useHorizonOcclusion" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Unlit" target={material} propertyName="unlit" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx

@@ -113,6 +113,8 @@ export class TexturePropertyGridComponent extends React.Component<ITextureProper
                 <CustomPropertyGridComponent globalState={this.props.globalState} target={texture}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
+                    <TextLineComponent label="Width" value={texture.getSize().width.toString()} />
+                    <TextLineComponent label="Height" value={texture.getSize().height.toString()} />
                     <TextLineComponent label="Unique ID" value={texture.uniqueId.toString()} />
                     <TextLineComponent label="Class" value={texture.getClassName()} />
                     <TextLineComponent label="Has alpha" value={texture.hasAlpha ? "Yes" : "No"} />

+ 0 - 80
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/axesViewerComponent.tsx

@@ -1,80 +0,0 @@
-import * as React from "react";
-
-import { Vector3, Tmp } from "babylonjs/Maths/math";
-import { TransformNode } from "babylonjs/Meshes/transformNode";
-import { AxesViewer } from "babylonjs/Debug/axesViewer";
-
-import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
-import { UtilityLayerRenderer } from 'babylonjs/Rendering/utilityLayerRenderer';
-import { GlobalState } from '../../../../globalState';
-
-interface IAxisViewerComponentProps {
-    node: TransformNode;
-    globalState: GlobalState;
-}
-
-export class AxesViewerComponent extends React.Component<IAxisViewerComponentProps, { displayAxis: boolean }> {
-    constructor(props: IAxisViewerComponentProps) {
-        super(props);
-        const node = this.props.node;
-
-        if (!node.reservedDataStore) {
-            node.reservedDataStore = {};
-        }
-
-        this.state = { displayAxis: (node.reservedDataStore && node.reservedDataStore.axisViewer) ? true : false };
-    }
-
-    shouldComponentUpdate(nextProps: IAxisViewerComponentProps, nextState: { displayAxis: boolean }) {
-        if (nextProps.node !== this.props.node) {
-            nextState.displayAxis = (nextProps.node.reservedDataStore && nextProps.node.reservedDataStore.axisViewer) ? true : false;
-        }
-
-        return true;
-    }
-
-    displayAxes() {
-        const node = this.props.node;
-        const scene = UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene;
-
-        if (node.reservedDataStore.axisViewer) {
-            node.reservedDataStore.axisViewer.dispose();
-            node.reservedDataStore.axisViewer = null;
-
-            scene.onBeforeRenderObservable.remove(node.reservedDataStore.onBeforeRenderObserver);
-            node.reservedDataStore.onBeforeRenderObserver = null;
-
-            this.setState({ displayAxis: false });
-
-            return;
-        }
-
-        const viewer = new AxesViewer(scene);
-        node.reservedDataStore.axisViewer = viewer;
-        const x = new Vector3(1, 0, 0);
-        const y = new Vector3(0, 1, 0);
-        const z = new Vector3(0, 0, 1);
-
-        viewer.xAxis.reservedDataStore = { hidden: true };
-        viewer.yAxis.reservedDataStore = { hidden: true };
-        viewer.zAxis.reservedDataStore = { hidden: true };
-
-        node.reservedDataStore.onBeforeRenderObserver = scene.onBeforeRenderObservable.add(() => {
-            let cameraMatrix = scene.activeCamera!.getWorldMatrix();
-            let matrix = node.getWorldMatrix();
-            let extend = Tmp.Vector3[0];
-            Vector3.TransformCoordinatesFromFloatsToRef(0, 0, 1, cameraMatrix, extend);
-
-            viewer.scaleLines = extend.length() / 10;
-            viewer.update(node.getAbsolutePosition(), Vector3.TransformNormal(x, matrix), Vector3.TransformNormal(y, matrix), Vector3.TransformNormal(z, matrix));
-        });
-
-        this.setState({ displayAxis: true });
-    }
-
-    render() {
-        return (
-            <CheckBoxLineComponent label="Display axes" isSelected={() => this.state.displayAxis} onSelect={() => this.displayAxes()} />
-        );
-    }
-}

+ 42 - 10
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx

@@ -16,12 +16,12 @@ import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 import { Vector3LineComponent } from "../../../lines/vector3LineComponent";
 import { SliderLineComponent } from "../../../lines/sliderLineComponent";
 import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent";
-import { AxesViewerComponent } from "./axesViewerComponent";
 import { FloatLineComponent } from "../../../lines/floatLineComponent";
 import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
 import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
 import { StandardMaterial } from 'babylonjs/Materials/standardMaterial';
+import { Color3LineComponent } from '../../../lines/color3LineComponent';
 
 interface IMeshPropertyGridComponentProps {
     globalState: GlobalState;
@@ -161,6 +161,15 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
         this.props.onSelectionChangedObservable.notifyObservers(mesh.material);
     }
 
+    onSourceMeshLink() {
+        if (!this.props.onSelectionChangedObservable) {
+            return;
+        }
+
+        const instanceMesh = this.props.mesh as any;
+        this.props.onSelectionChangedObservable.notifyObservers(instanceMesh.sourceMesh);
+    }
+
     convertPhysicsTypeToString(): string {
         const mesh = this.props.mesh;
         switch (mesh.physicsImpostor!.type) {
@@ -217,6 +226,10 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                         mesh.material &&
                         <TextLineComponent label="Material" value={mesh.material.name} onLink={() => this.onMaterialLink()} />
                     }
+                    {
+                        mesh.isAnInstance &&
+                        <TextLineComponent label="Source" value={(mesh as any).sourceMesh.name} onLink={() => this.onSourceMeshLink()} />
+                    }
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="TRANSFORMS">
                     <Vector3LineComponent label="Position" target={mesh} propertyName="position" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
@@ -231,7 +244,10 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                     <Vector3LineComponent label="Scaling" target={mesh} propertyName="scaling" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="DISPLAY" closed={true}>
-                    <SliderLineComponent label="Visibility" target={mesh} propertyName="visibility" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    {
+                        !mesh.isAnInstance &&
+                        <SliderLineComponent label="Visibility" target={mesh} propertyName="visibility" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    }
                     <FloatLineComponent lockObject={this.props.lockObject} label="Alpha index" target={mesh} propertyName="alphaIndex" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Receive shadows" target={mesh} propertyName="receiveShadows" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
@@ -255,13 +271,13 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                     <CheckBoxLineComponent label="Collisions" target={mesh} propertyName="checkCollisions" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <TextLineComponent label="Has normals" value={mesh.isVerticesDataPresent(VertexBuffer.NormalKind) ? "Yes" : "No"} />
                     <TextLineComponent label="Has vertex colors" value={mesh.isVerticesDataPresent(VertexBuffer.ColorKind) ? "Yes" : "No"} />
-                    <TextLineComponent label="has UV set 0" value={mesh.isVerticesDataPresent(VertexBuffer.UVKind) ? "Yes" : "No"} />
-                    <TextLineComponent label="has UV set 1" value={mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) ? "Yes" : "No"} />
-                    <TextLineComponent label="has UV set 2" value={mesh.isVerticesDataPresent(VertexBuffer.UV3Kind) ? "Yes" : "No"} />
-                    <TextLineComponent label="has UV set 3" value={mesh.isVerticesDataPresent(VertexBuffer.UV4Kind) ? "Yes" : "No"} />
-                    <TextLineComponent label="has tangents" value={mesh.isVerticesDataPresent(VertexBuffer.TangentKind) ? "Yes" : "No"} />
-                    <TextLineComponent label="has matrix weights" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind) ? "Yes" : "No"} />
-                    <TextLineComponent label="has matrix indices" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind) ? "Yes" : "No"} />
+                    <TextLineComponent label="Has UV set 0" value={mesh.isVerticesDataPresent(VertexBuffer.UVKind) ? "Yes" : "No"} />
+                    <TextLineComponent label="Has UV set 1" value={mesh.isVerticesDataPresent(VertexBuffer.UV2Kind) ? "Yes" : "No"} />
+                    <TextLineComponent label="Has UV set 2" value={mesh.isVerticesDataPresent(VertexBuffer.UV3Kind) ? "Yes" : "No"} />
+                    <TextLineComponent label="Has UV set 3" value={mesh.isVerticesDataPresent(VertexBuffer.UV4Kind) ? "Yes" : "No"} />
+                    <TextLineComponent label="Has tangents" value={mesh.isVerticesDataPresent(VertexBuffer.TangentKind) ? "Yes" : "No"} />
+                    <TextLineComponent label="Has matrix weights" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesWeightsKind) ? "Yes" : "No"} />
+                    <TextLineComponent label="Has matrix indices" value={mesh.isVerticesDataPresent(VertexBuffer.MatricesIndicesKind) ? "Yes" : "No"} />
                 </LineContainerComponent>
                 {
                     mesh.physicsImpostor != null &&
@@ -272,6 +288,23 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                         <TextLineComponent label="Type" value={this.convertPhysicsTypeToString()} />
                     </LineContainerComponent>
                 }
+                <LineContainerComponent globalState={this.props.globalState} title="EDGE RENDERING" closed={true}>
+                    <CheckBoxLineComponent label="Enable" target={mesh} isSelected={() => mesh.edgesRenderer != null} onSelect={value => {
+                        if (value) {
+                            mesh.enableEdgesRendering();
+                        } else {
+                            mesh.disableEdgesRendering();
+                        }
+                    }} />
+                    <SliderLineComponent label="Edge width" minimum={0} maximum={10} step={0.1} target={mesh} propertyName="edgesWidth" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <Color3LineComponent label="Edge color" target={mesh} propertyName="edgesColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
+                <LineContainerComponent globalState={this.props.globalState} title="OUTLINE & OVERLAY" closed={true}>
+                    <CheckBoxLineComponent label="Render overlay" target={mesh} propertyName="renderOverlay" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <Color3LineComponent label="Overlay color" target={mesh} propertyName="overlayColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Render outline" target={mesh} propertyName="renderOutline" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <Color3LineComponent label="Outline color" target={mesh} propertyName="outlineColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="DEBUG" closed={true}>
                     {
                         mesh.material &&
@@ -281,7 +314,6 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                         mesh.isVerticesDataPresent(VertexBuffer.NormalKind) &&
                         <CheckBoxLineComponent label="Render vertex normals" isSelected={() => renderNormalVectors} onSelect={() => this.renderNormalVectors()} />
                     }
-                    <AxesViewerComponent globalState={this.props.globalState} node={mesh} />
                     <CheckBoxLineComponent label="Render wireframe over mesh" isSelected={() => renderWireframeOver} onSelect={() => this.renderWireframeOver()} />
                 </LineContainerComponent>
             </div>

+ 0 - 4
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/transformNodePropertyGridComponent.tsx

@@ -9,7 +9,6 @@ import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 import { Vector3LineComponent } from "../../../lines/vector3LineComponent";
 import { TextLineComponent } from "../../../lines/textLineComponent";
 import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent";
-import { AxesViewerComponent } from "./axesViewerComponent";
 import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
 import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
@@ -51,9 +50,6 @@ export class TransformNodePropertyGridComponent extends React.Component<ITransfo
                     }
                     <Vector3LineComponent label="Scaling" target={transformNode} propertyName="scaling" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
-                <LineContainerComponent globalState={this.props.globalState} title="DEBUG" closed={true}>
-                    <AxesViewerComponent globalState={this.props.globalState} node={transformNode} />
-                </LineContainerComponent>
             </div>
         );
     }

+ 28 - 21
inspector/src/components/actionTabs/tabs/propertyGrids/postProcesses/defaultRenderingPipelinePropertyGridComponent.tsx

@@ -46,9 +46,9 @@ export class DefaultRenderingPipelinePropertyGridComponent extends React.Compone
             <div className="pane">
                 <CommonRenderingPipelinePropertyGridComponent globalState={this.props.globalState} lockObject={this.props.lockObject} renderPipeline={renderPipeline} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="BLOOM">
-                    <CheckBoxLineComponent label="Enabled" target={renderPipeline} 
-                    onValueChanged={() => this.forceUpdate()}
-                    propertyName="bloomEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Enabled" target={renderPipeline}
+                        onValueChanged={() => this.forceUpdate()}
+                        propertyName="bloomEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
                         renderPipeline.bloomEnabled &&
                         <div>
@@ -60,9 +60,9 @@ export class DefaultRenderingPipelinePropertyGridComponent extends React.Compone
                     }
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="CHROMATIC ABERRATION">
-                    <CheckBoxLineComponent label="Enabled" target={renderPipeline} 
-                    onValueChanged={() => this.forceUpdate()}
-                    propertyName="chromaticAberrationEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Enabled" target={renderPipeline}
+                        onValueChanged={() => this.forceUpdate()}
+                        propertyName="chromaticAberrationEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
                         renderPipeline.chromaticAberrationEnabled &&
                         <div>
@@ -74,9 +74,9 @@ export class DefaultRenderingPipelinePropertyGridComponent extends React.Compone
                     }
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="DEPTH OF FIELD">
-                    <CheckBoxLineComponent label="Enabled" target={renderPipeline} 
-                    onValueChanged={() => this.forceUpdate()}
-                    propertyName="depthOfFieldEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Enabled" target={renderPipeline}
+                        onValueChanged={() => this.forceUpdate()}
+                        propertyName="depthOfFieldEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
                         renderPipeline.depthOfFieldEnabled &&
                         <div>
@@ -84,7 +84,7 @@ export class DefaultRenderingPipelinePropertyGridComponent extends React.Compone
                             <SliderLineComponent label="fStop" minimum={0} maximum={32} step={0.1} target={renderPipeline.depthOfField} propertyName="fStop" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <SliderLineComponent label="Distance" minimum={0} maximum={camera.maxZ} step={0.1} target={renderPipeline.depthOfField} propertyName="focusDistance" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <SliderLineComponent label="Lens size" minimum={0} maximum={1000} step={1} target={renderPipeline.depthOfField} propertyName="lensSize" onPropertyChangedObservable={this.props.onPropertyChangedObservable} decimalCount={0} />
-                        </div>                    
+                        </div>
                     }
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="FXAA">
@@ -92,23 +92,30 @@ export class DefaultRenderingPipelinePropertyGridComponent extends React.Compone
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="GLOW LAYER">
                     <CheckBoxLineComponent label="Enabled" target={renderPipeline} propertyName="glowLayerEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    {
+                        renderPipeline.glowLayerEnabled &&
+                        <div>
+                            <SliderLineComponent label="Blur kernel size" minimum={1} maximum={128} step={1} decimalCount={0} target={renderPipeline.glowLayer} propertyName="blurKernelSize" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <SliderLineComponent label="Intensity" minimum={0} maximum={10} step={0.1} target={renderPipeline.glowLayer} propertyName="intensity" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                        </div>
+                    }
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="GRAIN">
-                    <CheckBoxLineComponent label="Enabled" target={renderPipeline} 
-                    onValueChanged={() => this.forceUpdate()}
-                    propertyName="grainEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Enabled" target={renderPipeline}
+                        onValueChanged={() => this.forceUpdate()}
+                        propertyName="grainEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
                         renderPipeline.grainEnabled &&
                         <div>
                             <CheckBoxLineComponent label="Animated" target={renderPipeline.grain} propertyName="animated" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <SliderLineComponent label="Intensity" minimum={0} maximum={50} step={0.1} target={renderPipeline.grain} propertyName="intensity" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                        </div>                    
+                        </div>
                     }
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="IMAGE PROCESSING">
-                    <CheckBoxLineComponent label="Enabled" target={renderPipeline} 
-                    onValueChanged={() => this.forceUpdate()}
-                    propertyName="imageProcessingEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Enabled" target={renderPipeline}
+                        onValueChanged={() => this.forceUpdate()}
+                        propertyName="imageProcessingEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
                         renderPipeline.imageProcessing &&
                         <div>
@@ -128,15 +135,15 @@ export class DefaultRenderingPipelinePropertyGridComponent extends React.Compone
                     }
                 </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="SHARPEN">
-                    <CheckBoxLineComponent label="Enabled" target={renderPipeline} 
-                    onValueChanged={() => this.forceUpdate()}
-                    propertyName="sharpenEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <CheckBoxLineComponent label="Enabled" target={renderPipeline}
+                        onValueChanged={() => this.forceUpdate()}
+                        propertyName="sharpenEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
                         renderPipeline.sharpenEnabled &&
                         <div>
                             <SliderLineComponent label="Color amount" minimum={0} maximum={1} step={0.05} target={renderPipeline.sharpen} propertyName="colorAmount" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <SliderLineComponent label="Edge amount" minimum={0} maximum={5} step={0.05} target={renderPipeline.sharpen} propertyName="edgeAmount" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                        </div>                    
+                        </div>
                     }
                 </LineContainerComponent>
             </div>

+ 1 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/scenePropertyGridComponent.tsx

@@ -147,7 +147,7 @@ export class ScenePropertyGridComponent extends React.Component<IScenePropertyGr
                     <FileButtonLineComponent label="Update environment texture" onClick={(file) => this.updateEnvironmentTexture(file)} accept=".dds, .env" />
                     <FogPropertyGridComponent globalState={this.props.globalState} lockObject={this.props.lockObject} scene={scene} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
-                <LineContainerComponent globalState={this.props.globalState} title="IMAGE PROCESSING">
+                <LineContainerComponent globalState={this.props.globalState} title="MATERIAL IMAGE PROCESSING">
                     <SliderLineComponent minimum={0} maximum={4} step={0.1} label="Contrast" target={imageProcessing} propertyName="contrast" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent minimum={0} maximum={4} step={0.1} label="Exposure" target={imageProcessing} propertyName="exposure" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Tone mapping" target={imageProcessing} propertyName="toneMappingEnabled" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 1 - 1
inspector/src/components/actionTabs/tabs/toolsTabComponent.tsx

@@ -145,7 +145,7 @@ export class ToolsTabComponent extends PaneComponent {
                     <ButtonLineComponent label="Export to GLB" onClick={() => this.exportGLTF()} />
                     <ButtonLineComponent label="Export to Babylon" onClick={() => this.exportBabylon()} />
                     {
-                        !scene.getEngine().premultipliedAlpha && scene.environmentTexture && scene.activeCamera &&
+                        !scene.getEngine().premultipliedAlpha && scene.environmentTexture && (scene.environmentTexture as CubeTexture).isPrefiltered && scene.activeCamera &&
                         <ButtonLineComponent label="Generate .env texture" onClick={() => this.createEnvTexture()} />
                     }
                 </LineContainerComponent>

+ 16 - 16
inspector/src/components/replayRecorder.ts

@@ -23,35 +23,35 @@ export class ReplayRecorder {
 
         let value = event.value;
 
-        if (value.w) { // Quaternion
+        if (value.w !== undefined) { // Quaternion
             value = `new BABYLON.Quaternion(${value.x}, ${value.y}, ${value.z}, ${value.w})`;
-        } else if (value.z) { // Vector3
+        } else if (value.z !== undefined) { // Vector3
             value = `new BABYLON.Vector3(${value.x}, ${value.y}, ${value.z})`;
-        } else if (value.y) { // Vector2
+        } else if (value.y !== undefined) { // Vector2
             value = `new BABYLON.Vector2(${value.x}, ${value.y})`;
-        } else if (value.a) { // Color4
+        } else if (value.a !== undefined) { // Color4
             value = `new BABYLON.Color4(${value.r}, ${value.g}, ${value.b}, ${value.a})`;
-        } else if (value.b) { // Color3
+        } else if (value.b !== undefined) { // Color3
             value = `new BABYLON.Color3(${value.r}, ${value.g}, ${value.b})`;
         }
 
         let target = event.object.getClassName().toLowerCase();
 
-        if (event.object.uniqueId) {
+        if (event.object.id) {
             if (target === "Scene") {
                 target = `scene`;
-            } else if (target.indexOf("camera")) {
-                target = `scene.getCameraByUniqueID(${event.object.uniqueId})`;
-            } else if (target.indexOf("mesh")) {
-                target = `scene.getMeshByUniqueID(${event.object.uniqueId})`;
-            } else if (target.indexOf("light")) {
-                target = `scene.getLightByUniqueID(${event.object.uniqueId})`;
+            } else if (target.indexOf("camera") > -1) {
+                target = `scene.getCameraByID("${event.object.id}")`;
+            } else if (target.indexOf("mesh") > -1) {
+                target = `scene.getMeshByID("${event.object.id}")`;
+            } else if (target.indexOf("light") > -1) {
+                target = `scene.getLightByID("${event.object.id}")`;
             } else if (target === "transformnode") {
-                target = `scene.getTransformNodeByUniqueID(${event.object.uniqueId})`;
+                target = `scene.getTransformNodeByID("${event.object.id}")`;
             } else if (target === "skeleton") {
-                target = `scene.getSkeletonByUniqueId(${event.object.uniqueId})`;
-            } else if (target.indexOf("material")) {
-                target = `scene.getMaterialByUniqueID(${event.object.uniqueId})`;
+                target = `scene.getSkeletonById("${event.object.id}")`;
+            } else if (target.indexOf("material") > -1) {
+                target = `scene.getMaterialByID("${event.object.id}")`;
             }
         }
 

+ 0 - 0
inspector/src/components/sceneExplorer/entities/lightTreeItemComponent.tsx


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