瀏覽代碼

Merge branch 'master' into master

David Catuhe 6 年之前
父節點
當前提交
3e294883fb
共有 56 個文件被更改,包括 1482 次插入483 次删除
  1. 54 12
      Playground/babylon.d.txt
  2. 55 12
      dist/preview release/babylon.d.ts
  3. 2 2
      dist/preview release/babylon.js
  4. 257 124
      dist/preview release/babylon.max.js
  5. 1 1
      dist/preview release/babylon.max.js.map
  6. 111 25
      dist/preview release/babylon.module.d.ts
  7. 55 12
      dist/preview release/documentation.d.ts
  8. 36 3
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  9. 6 6
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  10. 219 68
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  11. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  12. 74 6
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  13. 1 1
      dist/preview release/packagesSizeBaseLine.json
  14. 111 25
      dist/preview release/viewer/babylon.module.d.ts
  15. 27 27
      dist/preview release/viewer/babylon.viewer.js
  16. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  17. 5 1
      dist/preview release/what's new.md
  18. 1 1
      nodeEditor/src/components/diagram/defaultNodeModel.ts
  19. 8 0
      nodeEditor/src/components/diagram/defaultPortModel.ts
  20. 1 1
      nodeEditor/src/components/diagram/diagram.scss
  21. 2 23
      nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx
  22. 4 1
      nodeEditor/src/components/diagram/input/inputNodeWidget.tsx
  23. 8 2
      nodeEditor/src/components/diagram/light/lightPropertyTabComponent.tsx
  24. 8 2
      nodeEditor/src/components/log/log.scss
  25. 10 4
      nodeEditor/src/components/log/logComponent.tsx
  26. 1 1
      nodeEditor/src/components/nodeList/nodeList.scss
  27. 1 1
      nodeEditor/src/components/propertyTab/propertyTab.scss
  28. 65 0
      nodeEditor/src/dataStorage.ts
  29. 2 1
      nodeEditor/src/globalState.ts
  30. 66 4
      nodeEditor/src/graphEditor.tsx
  31. 15 4
      nodeEditor/src/main.scss
  32. 3 29
      nodeEditor/src/sharedComponents/lineContainerComponent.tsx
  33. 7 2
      nodeEditor/src/sharedComponents/optionsLineComponent.tsx
  34. 25 0
      nodeEditor/src/stringTools.ts
  35. 1 1
      src/Audio/audioSceneComponent.ts
  36. 9 12
      src/Audio/sound.ts
  37. 7 2
      src/Behaviors/Meshes/pointerDragBehavior.ts
  38. 24 3
      src/Bones/skeleton.ts
  39. 20 1
      src/Debug/debugLayer.ts
  40. 6 0
      src/Engines/Processors/shaderCodeCursor.ts
  41. 3 0
      src/Layers/effectLayer.ts
  42. 1 1
      src/Lights/Shadows/shadowGenerator.ts
  43. 71 39
      src/Materials/Node/Blocks/Dual/lightBlock.ts
  44. 4 0
      src/Materials/Node/nodeMaterial.ts
  45. 10 0
      src/Materials/Node/nodeMaterialBlock.ts
  46. 17 6
      src/Materials/Node/nodeMaterialBlockConnectionPoint.ts
  47. 5 0
      src/Materials/Node/nodeMaterialBuildState.ts
  48. 7 0
      src/Materials/Node/nodeMaterialBuildStateSharedData.ts
  49. 4 2
      src/Materials/PBR/pbrBaseMaterial.ts
  50. 2 2
      src/Materials/PBR/pbrMaterial.ts
  51. 2 2
      src/Materials/materialHelper.ts
  52. 9 0
      src/Meshes/abstractMesh.ts
  53. 5 3
      src/Misc/basis.ts
  54. 9 2
      src/Misc/observable.ts
  55. 18 3
      src/Morph/morphTargetManager.ts
  56. 5 1
      src/PostProcesses/volumetricLightScatteringPostProcess.ts

+ 54 - 12
Playground/babylon.d.txt

@@ -4350,6 +4350,10 @@ declare module BABYLON {
         private _eventState;
         private _onObserverAdded;
         /**
+         * Gets the list of observers
+         */
+        readonly observers: Array<Observer<T>>;
+        /**
          * Creates a new observable
          * @param onObserverAdded defines a callback to call when a new observer is added
          */
@@ -9873,7 +9877,7 @@ declare module BABYLON {
         private _useTextureToStoreBoneMatrices;
         /**
          * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-         * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+         * Please note that this option is not available if the hardware does not support it
          */
         useTextureToStoreBoneMatrices: boolean;
         private _animationPropertiesOverride;
@@ -9927,9 +9931,10 @@ declare module BABYLON {
         getTransformMatrices(mesh: AbstractMesh): Float32Array;
         /**
          * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+         * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
          * @returns a raw texture containing the data
          */
-        getTransformMatrixTexture(): Nullable<RawTexture>;
+        getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture>;
         /**
          * Gets the current hosting scene
          * @returns a scene object
@@ -10199,6 +10204,18 @@ declare module BABYLON {
         private _uniqueId;
         private _tempInfluences;
         /**
+         * Gets or sets a boolean indicating if normals must be morphed
+         */
+        enableNormalMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if tangents must be morphed
+         */
+        enableTangentMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if UV must be morphed
+         */
+        enableUVMorphing: boolean;
+        /**
          * Creates a new MorphTargetManager
          * @param scene defines the current scene
          */
@@ -24343,6 +24360,7 @@ declare module BABYLON {
             freezeWorldMatrix: Nullable<boolean>;
         };
         /** @hidden */
private _bonesTransformMatrices: Nullable<Float32Array>;
+        /** @hidden */
private _transformMatrixTexture: Nullable<RawTexture>;
         /**
          * Gets or sets a skeleton to apply skining transformations
          * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -33628,6 +33646,10 @@ declare module BABYLON {
          * Defines an optional offset (in seconds) inside the sound file
          */
         offset?: number;
+        /**
+         * If true, URLs will not be required to state the audio file codec to use.
+         */
+        skipCodecCheck?: boolean;
     }
     /**
      * Defines a sound that can be played in the application.
@@ -35539,6 +35561,10 @@ declare module BABYLON {
          */
         enabled: boolean;
         /**
+         * If pointer events should start and release the drag (Default: true)
+         */
+        startAndReleaseDragOnPointerEvents: boolean;
+        /**
          * If camera controls should be detached during the drag
          */
         detachCameraControls: boolean;
@@ -40834,15 +40860,11 @@ declare module BABYLON {
         static InspectorURL: string;
         private _scene;
         private BJSINSPECTOR;
+        private _onPropertyChangedObservable?;
         /**
          * Observable triggered when a property is changed through the inspector.
          */
-        onPropertyChangedObservable: Observable<{
-            object: any;
-            property: string;
-            value: any;
-            initialValue: any;
-        }>;
+        readonly onPropertyChangedObservable: any;
         /**
          * Instantiates a new debug layer.
          * The debug layer (aka Inspector) is the go to tool in order to better understand
@@ -45722,9 +45744,9 @@ declare module BABYLON {
         /**
          * Let user defines the brdf lookup texture used for IBL.
          * A default 8bit version is embedded but you could point at :
-         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
          * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
          * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
          */
         environmentBRDFTexture: Nullable<BaseTexture>;
@@ -46743,7 +46765,7 @@ declare module BABYLON {
         /**
          * Gets the rendering group id the layer should render in.
          */
-        readonly renderingGroupId: number;
+        renderingGroupId: number;
         /**
          * An event triggered when the effect layer has been disposed.
          */
@@ -50027,6 +50049,10 @@ declare module BABYLON {
         */
         repeatableContentBlocks: NodeMaterialBlock[];
         /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
          * List of blocks that can block the isReady function for the material
          */
         blockingBlocks: NodeMaterialBlock[];
@@ -50141,6 +50167,7 @@ declare module BABYLON {
                 search: RegExp;
                 replace: string;
             }[];
+            repeatKey?: string;
         }): string;
         /** @hidden */
private _emitFunctionFromInclude(includeName: string, comments: string, options?: {
             repeatKey?: string;
@@ -50589,6 +50616,13 @@ declare module BABYLON {
         }): this | undefined;
         protected _buildBlock(state: NodeMaterialBuildState): void;
         /**
+         * Add uniforms, samplers and uniform buffers at compilation time
+         * @param state defines the state to update
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to update
+         */
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        /**
          * Add potential fallbacks if shader compilation fails
          * @param mesh defines the mesh to be rendered
          * @param fallbacks defines the current prioritized list of fallbacks
@@ -50746,6 +50780,12 @@ declare module BABYLON {
         wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
+         * Gets an boolean indicating if the current point can be connected to another point
+         * @param connectionPoint defines the other connection point
+         * @returns true if the connection is possible
+         */
+        canConnectTo(connectionPoint: NodeMaterialConnectionPoint): boolean;
+        /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
          * @returns the current connection point
@@ -51232,7 +51272,8 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component
+        * Gets the light input component.
+        * If not defined, all lights will be considered
         */
         readonly light: NodeMaterialConnectionPoint;
         /**
@@ -51249,6 +51290,7 @@ declare module BABYLON {
         readonly specularOutput: NodeMaterialConnectionPoint;
         autoConfigure(): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this | undefined;

+ 55 - 12
dist/preview release/babylon.d.ts

@@ -4353,6 +4353,10 @@ declare module BABYLON {
         private _eventState;
         private _onObserverAdded;
         /**
+         * Gets the list of observers
+         */
+        readonly observers: Array<Observer<T>>;
+        /**
          * Creates a new observable
          * @param onObserverAdded defines a callback to call when a new observer is added
          */
@@ -10008,7 +10012,7 @@ declare module BABYLON {
         private _useTextureToStoreBoneMatrices;
         /**
          * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-         * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+         * Please note that this option is not available if the hardware does not support it
          */
         useTextureToStoreBoneMatrices: boolean;
         private _animationPropertiesOverride;
@@ -10062,9 +10066,10 @@ declare module BABYLON {
         getTransformMatrices(mesh: AbstractMesh): Float32Array;
         /**
          * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+         * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
          * @returns a raw texture containing the data
          */
-        getTransformMatrixTexture(): Nullable<RawTexture>;
+        getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture>;
         /**
          * Gets the current hosting scene
          * @returns a scene object
@@ -10338,6 +10343,18 @@ declare module BABYLON {
         private _uniqueId;
         private _tempInfluences;
         /**
+         * Gets or sets a boolean indicating if normals must be morphed
+         */
+        enableNormalMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if tangents must be morphed
+         */
+        enableTangentMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if UV must be morphed
+         */
+        enableUVMorphing: boolean;
+        /**
          * Creates a new MorphTargetManager
          * @param scene defines the current scene
          */
@@ -24789,6 +24806,8 @@ declare module BABYLON {
         };
         /** @hidden */
         _bonesTransformMatrices: Nullable<Float32Array>;
+        /** @hidden */
+        _transformMatrixTexture: Nullable<RawTexture>;
         /**
          * Gets or sets a skeleton to apply skining transformations
          * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -34300,6 +34319,10 @@ declare module BABYLON {
          * Defines an optional offset (in seconds) inside the sound file
          */
         offset?: number;
+        /**
+         * If true, URLs will not be required to state the audio file codec to use.
+         */
+        skipCodecCheck?: boolean;
     }
     /**
      * Defines a sound that can be played in the application.
@@ -36231,6 +36254,10 @@ declare module BABYLON {
          */
         enabled: boolean;
         /**
+         * If pointer events should start and release the drag (Default: true)
+         */
+        startAndReleaseDragOnPointerEvents: boolean;
+        /**
          * If camera controls should be detached during the drag
          */
         detachCameraControls: boolean;
@@ -41563,15 +41590,11 @@ declare module BABYLON {
         static InspectorURL: string;
         private _scene;
         private BJSINSPECTOR;
+        private _onPropertyChangedObservable?;
         /**
          * Observable triggered when a property is changed through the inspector.
          */
-        onPropertyChangedObservable: Observable<{
-            object: any;
-            property: string;
-            value: any;
-            initialValue: any;
-        }>;
+        readonly onPropertyChangedObservable: any;
         /**
          * Instantiates a new debug layer.
          * The debug layer (aka Inspector) is the go to tool in order to better understand
@@ -46484,9 +46507,9 @@ declare module BABYLON {
         /**
          * Let user defines the brdf lookup texture used for IBL.
          * A default 8bit version is embedded but you could point at :
-         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
          * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
          * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
          */
         environmentBRDFTexture: Nullable<BaseTexture>;
@@ -47506,7 +47529,7 @@ declare module BABYLON {
         /**
          * Gets the rendering group id the layer should render in.
          */
-        readonly renderingGroupId: number;
+        renderingGroupId: number;
         /**
          * An event triggered when the effect layer has been disposed.
          */
@@ -50805,6 +50828,10 @@ declare module BABYLON {
         */
         repeatableContentBlocks: NodeMaterialBlock[];
         /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
          * List of blocks that can block the isReady function for the material
          */
         blockingBlocks: NodeMaterialBlock[];
@@ -50928,6 +50955,7 @@ declare module BABYLON {
                 search: RegExp;
                 replace: string;
             }[];
+            repeatKey?: string;
         }): string;
         /** @hidden */
         _emitFunctionFromInclude(includeName: string, comments: string, options?: {
@@ -51383,6 +51411,13 @@ declare module BABYLON {
         }): this | undefined;
         protected _buildBlock(state: NodeMaterialBuildState): void;
         /**
+         * Add uniforms, samplers and uniform buffers at compilation time
+         * @param state defines the state to update
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to update
+         */
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        /**
          * Add potential fallbacks if shader compilation fails
          * @param mesh defines the mesh to be rendered
          * @param fallbacks defines the current prioritized list of fallbacks
@@ -51546,6 +51581,12 @@ declare module BABYLON {
         wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
+         * Gets an boolean indicating if the current point can be connected to another point
+         * @param connectionPoint defines the other connection point
+         * @returns true if the connection is possible
+         */
+        canConnectTo(connectionPoint: NodeMaterialConnectionPoint): boolean;
+        /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
          * @returns the current connection point
@@ -52032,7 +52073,8 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component
+        * Gets the light input component.
+        * If not defined, all lights will be considered
         */
         readonly light: NodeMaterialConnectionPoint;
         /**
@@ -52049,6 +52091,7 @@ declare module BABYLON {
         readonly specularOutput: NodeMaterialConnectionPoint;
         autoConfigure(): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this | undefined;

文件差異過大導致無法顯示
+ 2 - 2
dist/preview release/babylon.js


文件差異過大導致無法顯示
+ 257 - 124
dist/preview release/babylon.max.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/babylon.max.js.map


+ 111 - 25
dist/preview release/babylon.module.d.ts

@@ -4356,6 +4356,10 @@ declare module "babylonjs/Misc/observable" {
         private _eventState;
         private _onObserverAdded;
         /**
+         * Gets the list of observers
+         */
+        readonly observers: Array<Observer<T>>;
+        /**
          * Creates a new observable
          * @param onObserverAdded defines a callback to call when a new observer is added
          */
@@ -10140,7 +10144,7 @@ declare module "babylonjs/Bones/skeleton" {
         private _useTextureToStoreBoneMatrices;
         /**
          * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-         * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+         * Please note that this option is not available if the hardware does not support it
          */
         useTextureToStoreBoneMatrices: boolean;
         private _animationPropertiesOverride;
@@ -10194,9 +10198,10 @@ declare module "babylonjs/Bones/skeleton" {
         getTransformMatrices(mesh: AbstractMesh): Float32Array;
         /**
          * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+         * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
          * @returns a raw texture containing the data
          */
-        getTransformMatrixTexture(): Nullable<RawTexture>;
+        getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture>;
         /**
          * Gets the current hosting scene
          * @returns a scene object
@@ -10479,6 +10484,18 @@ declare module "babylonjs/Morph/morphTargetManager" {
         private _uniqueId;
         private _tempInfluences;
         /**
+         * Gets or sets a boolean indicating if normals must be morphed
+         */
+        enableNormalMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if tangents must be morphed
+         */
+        enableTangentMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if UV must be morphed
+         */
+        enableUVMorphing: boolean;
+        /**
          * Creates a new MorphTargetManager
          * @param scene defines the current scene
          */
@@ -25126,6 +25143,7 @@ declare module "babylonjs/Meshes/abstractMesh" {
     import { IEdgesRenderer } from "babylonjs/Rendering/edgesRenderer";
     import { SolidParticle } from "babylonjs/Particles/solidParticle";
     import { AbstractActionManager } from "babylonjs/Actions/abstractActionManager";
+    import { RawTexture } from "babylonjs/Materials/Textures/rawTexture";
     import { Ray } from "babylonjs/Culling/ray";
     import { Collider } from "babylonjs/Collisions/collider";
     import { TrianglePickingPredicate } from "babylonjs/Culling/ray";
@@ -25466,6 +25484,8 @@ declare module "babylonjs/Meshes/abstractMesh" {
         };
         /** @hidden */
         _bonesTransformMatrices: Nullable<Float32Array>;
+        /** @hidden */
+        _transformMatrixTexture: Nullable<RawTexture>;
         /**
          * Gets or sets a skeleton to apply skining transformations
          * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -35198,6 +35218,10 @@ declare module "babylonjs/Audio/sound" {
          * Defines an optional offset (in seconds) inside the sound file
          */
         offset?: number;
+        /**
+         * If true, URLs will not be required to state the audio file codec to use.
+         */
+        skipCodecCheck?: boolean;
     }
     /**
      * Defines a sound that can be played in the application.
@@ -37238,6 +37262,10 @@ declare module "babylonjs/Behaviors/Meshes/pointerDragBehavior" {
          */
         enabled: boolean;
         /**
+         * If pointer events should start and release the drag (Default: true)
+         */
+        startAndReleaseDragOnPointerEvents: boolean;
+        /**
          * If camera controls should be detached during the drag
          */
         detachCameraControls: boolean;
@@ -42963,7 +42991,6 @@ declare module "babylonjs/Debug/boneAxesViewer" {
     }
 }
 declare module "babylonjs/Debug/debugLayer" {
-    import { Observable } from "babylonjs/Misc/observable";
     import { Scene } from "babylonjs/scene";
     /**
      * Interface used to define scene explorer extensibility option
@@ -43064,15 +43091,11 @@ declare module "babylonjs/Debug/debugLayer" {
         static InspectorURL: string;
         private _scene;
         private BJSINSPECTOR;
+        private _onPropertyChangedObservable?;
         /**
          * Observable triggered when a property is changed through the inspector.
          */
-        onPropertyChangedObservable: Observable<{
-            object: any;
-            property: string;
-            value: any;
-            initialValue: any;
-        }>;
+        readonly onPropertyChangedObservable: any;
         /**
          * Instantiates a new debug layer.
          * The debug layer (aka Inspector) is the go to tool in order to better understand
@@ -48395,9 +48418,9 @@ declare module "babylonjs/Materials/PBR/pbrMaterial" {
         /**
          * Let user defines the brdf lookup texture used for IBL.
          * A default 8bit version is embedded but you could point at :
-         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
          * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
          * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
          */
         environmentBRDFTexture: Nullable<BaseTexture>;
@@ -49500,7 +49523,7 @@ declare module "babylonjs/Layers/effectLayer" {
         /**
          * Gets the rendering group id the layer should render in.
          */
-        readonly renderingGroupId: number;
+        renderingGroupId: number;
         /**
          * An event triggered when the effect layer has been disposed.
          */
@@ -53059,6 +53082,10 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildStateSharedData" {
         */
         repeatableContentBlocks: NodeMaterialBlock[];
         /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
          * List of blocks that can block the isReady function for the material
          */
         blockingBlocks: NodeMaterialBlock[];
@@ -53187,6 +53214,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
                 search: RegExp;
                 replace: string;
             }[];
+            repeatKey?: string;
         }): string;
         /** @hidden */
         _emitFunctionFromInclude(includeName: string, comments: string, options?: {
@@ -53674,6 +53702,13 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlock" {
         }): this | undefined;
         protected _buildBlock(state: NodeMaterialBuildState): void;
         /**
+         * Add uniforms, samplers and uniform buffers at compilation time
+         * @param state defines the state to update
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to update
+         */
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        /**
          * Add potential fallbacks if shader compilation fails
          * @param mesh defines the mesh to be rendered
          * @param fallbacks defines the current prioritized list of fallbacks
@@ -53845,6 +53880,12 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint" {
         wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
+         * Gets an boolean indicating if the current point can be connected to another point
+         * @param connectionPoint defines the other connection point
+         * @returns true if the connection is possible
+         */
+        canConnectTo(connectionPoint: NodeMaterialConnectionPoint): boolean;
+        /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
          * @returns the current connection point
@@ -54407,7 +54448,8 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/lightBlock" {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component
+        * Gets the light input component.
+        * If not defined, all lights will be considered
         */
         readonly light: NodeMaterialConnectionPoint;
         /**
@@ -54424,6 +54466,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/lightBlock" {
         readonly specularOutput: NodeMaterialConnectionPoint;
         autoConfigure(): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
@@ -67359,6 +67402,10 @@ declare module BABYLON {
         private _eventState;
         private _onObserverAdded;
         /**
+         * Gets the list of observers
+         */
+        readonly observers: Array<Observer<T>>;
+        /**
          * Creates a new observable
          * @param onObserverAdded defines a callback to call when a new observer is added
          */
@@ -73014,7 +73061,7 @@ declare module BABYLON {
         private _useTextureToStoreBoneMatrices;
         /**
          * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-         * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+         * Please note that this option is not available if the hardware does not support it
          */
         useTextureToStoreBoneMatrices: boolean;
         private _animationPropertiesOverride;
@@ -73068,9 +73115,10 @@ declare module BABYLON {
         getTransformMatrices(mesh: AbstractMesh): Float32Array;
         /**
          * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+         * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
          * @returns a raw texture containing the data
          */
-        getTransformMatrixTexture(): Nullable<RawTexture>;
+        getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture>;
         /**
          * Gets the current hosting scene
          * @returns a scene object
@@ -73344,6 +73392,18 @@ declare module BABYLON {
         private _uniqueId;
         private _tempInfluences;
         /**
+         * Gets or sets a boolean indicating if normals must be morphed
+         */
+        enableNormalMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if tangents must be morphed
+         */
+        enableTangentMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if UV must be morphed
+         */
+        enableUVMorphing: boolean;
+        /**
          * Creates a new MorphTargetManager
          * @param scene defines the current scene
          */
@@ -87795,6 +87855,8 @@ declare module BABYLON {
         };
         /** @hidden */
         _bonesTransformMatrices: Nullable<Float32Array>;
+        /** @hidden */
+        _transformMatrixTexture: Nullable<RawTexture>;
         /**
          * Gets or sets a skeleton to apply skining transformations
          * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -97306,6 +97368,10 @@ declare module BABYLON {
          * Defines an optional offset (in seconds) inside the sound file
          */
         offset?: number;
+        /**
+         * If true, URLs will not be required to state the audio file codec to use.
+         */
+        skipCodecCheck?: boolean;
     }
     /**
      * Defines a sound that can be played in the application.
@@ -99237,6 +99303,10 @@ declare module BABYLON {
          */
         enabled: boolean;
         /**
+         * If pointer events should start and release the drag (Default: true)
+         */
+        startAndReleaseDragOnPointerEvents: boolean;
+        /**
          * If camera controls should be detached during the drag
          */
         detachCameraControls: boolean;
@@ -104569,15 +104639,11 @@ declare module BABYLON {
         static InspectorURL: string;
         private _scene;
         private BJSINSPECTOR;
+        private _onPropertyChangedObservable?;
         /**
          * Observable triggered when a property is changed through the inspector.
          */
-        onPropertyChangedObservable: Observable<{
-            object: any;
-            property: string;
-            value: any;
-            initialValue: any;
-        }>;
+        readonly onPropertyChangedObservable: any;
         /**
          * Instantiates a new debug layer.
          * The debug layer (aka Inspector) is the go to tool in order to better understand
@@ -109490,9 +109556,9 @@ declare module BABYLON {
         /**
          * Let user defines the brdf lookup texture used for IBL.
          * A default 8bit version is embedded but you could point at :
-         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
          * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
          * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
          */
         environmentBRDFTexture: Nullable<BaseTexture>;
@@ -110512,7 +110578,7 @@ declare module BABYLON {
         /**
          * Gets the rendering group id the layer should render in.
          */
-        readonly renderingGroupId: number;
+        renderingGroupId: number;
         /**
          * An event triggered when the effect layer has been disposed.
          */
@@ -113811,6 +113877,10 @@ declare module BABYLON {
         */
         repeatableContentBlocks: NodeMaterialBlock[];
         /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
          * List of blocks that can block the isReady function for the material
          */
         blockingBlocks: NodeMaterialBlock[];
@@ -113934,6 +114004,7 @@ declare module BABYLON {
                 search: RegExp;
                 replace: string;
             }[];
+            repeatKey?: string;
         }): string;
         /** @hidden */
         _emitFunctionFromInclude(includeName: string, comments: string, options?: {
@@ -114389,6 +114460,13 @@ declare module BABYLON {
         }): this | undefined;
         protected _buildBlock(state: NodeMaterialBuildState): void;
         /**
+         * Add uniforms, samplers and uniform buffers at compilation time
+         * @param state defines the state to update
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to update
+         */
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        /**
          * Add potential fallbacks if shader compilation fails
          * @param mesh defines the mesh to be rendered
          * @param fallbacks defines the current prioritized list of fallbacks
@@ -114552,6 +114630,12 @@ declare module BABYLON {
         wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
+         * Gets an boolean indicating if the current point can be connected to another point
+         * @param connectionPoint defines the other connection point
+         * @returns true if the connection is possible
+         */
+        canConnectTo(connectionPoint: NodeMaterialConnectionPoint): boolean;
+        /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
          * @returns the current connection point
@@ -115038,7 +115122,8 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component
+        * Gets the light input component.
+        * If not defined, all lights will be considered
         */
         readonly light: NodeMaterialConnectionPoint;
         /**
@@ -115055,6 +115140,7 @@ declare module BABYLON {
         readonly specularOutput: NodeMaterialConnectionPoint;
         autoConfigure(): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this | undefined;

+ 55 - 12
dist/preview release/documentation.d.ts

@@ -4353,6 +4353,10 @@ declare module BABYLON {
         private _eventState;
         private _onObserverAdded;
         /**
+         * Gets the list of observers
+         */
+        readonly observers: Array<Observer<T>>;
+        /**
          * Creates a new observable
          * @param onObserverAdded defines a callback to call when a new observer is added
          */
@@ -10008,7 +10012,7 @@ declare module BABYLON {
         private _useTextureToStoreBoneMatrices;
         /**
          * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-         * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+         * Please note that this option is not available if the hardware does not support it
          */
         useTextureToStoreBoneMatrices: boolean;
         private _animationPropertiesOverride;
@@ -10062,9 +10066,10 @@ declare module BABYLON {
         getTransformMatrices(mesh: AbstractMesh): Float32Array;
         /**
          * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+         * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
          * @returns a raw texture containing the data
          */
-        getTransformMatrixTexture(): Nullable<RawTexture>;
+        getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture>;
         /**
          * Gets the current hosting scene
          * @returns a scene object
@@ -10338,6 +10343,18 @@ declare module BABYLON {
         private _uniqueId;
         private _tempInfluences;
         /**
+         * Gets or sets a boolean indicating if normals must be morphed
+         */
+        enableNormalMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if tangents must be morphed
+         */
+        enableTangentMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if UV must be morphed
+         */
+        enableUVMorphing: boolean;
+        /**
          * Creates a new MorphTargetManager
          * @param scene defines the current scene
          */
@@ -24789,6 +24806,8 @@ declare module BABYLON {
         };
         /** @hidden */
         _bonesTransformMatrices: Nullable<Float32Array>;
+        /** @hidden */
+        _transformMatrixTexture: Nullable<RawTexture>;
         /**
          * Gets or sets a skeleton to apply skining transformations
          * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -34300,6 +34319,10 @@ declare module BABYLON {
          * Defines an optional offset (in seconds) inside the sound file
          */
         offset?: number;
+        /**
+         * If true, URLs will not be required to state the audio file codec to use.
+         */
+        skipCodecCheck?: boolean;
     }
     /**
      * Defines a sound that can be played in the application.
@@ -36231,6 +36254,10 @@ declare module BABYLON {
          */
         enabled: boolean;
         /**
+         * If pointer events should start and release the drag (Default: true)
+         */
+        startAndReleaseDragOnPointerEvents: boolean;
+        /**
          * If camera controls should be detached during the drag
          */
         detachCameraControls: boolean;
@@ -41563,15 +41590,11 @@ declare module BABYLON {
         static InspectorURL: string;
         private _scene;
         private BJSINSPECTOR;
+        private _onPropertyChangedObservable?;
         /**
          * Observable triggered when a property is changed through the inspector.
          */
-        onPropertyChangedObservable: Observable<{
-            object: any;
-            property: string;
-            value: any;
-            initialValue: any;
-        }>;
+        readonly onPropertyChangedObservable: any;
         /**
          * Instantiates a new debug layer.
          * The debug layer (aka Inspector) is the go to tool in order to better understand
@@ -46484,9 +46507,9 @@ declare module BABYLON {
         /**
          * Let user defines the brdf lookup texture used for IBL.
          * A default 8bit version is embedded but you could point at :
-         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
          * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
          * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
          */
         environmentBRDFTexture: Nullable<BaseTexture>;
@@ -47506,7 +47529,7 @@ declare module BABYLON {
         /**
          * Gets the rendering group id the layer should render in.
          */
-        readonly renderingGroupId: number;
+        renderingGroupId: number;
         /**
          * An event triggered when the effect layer has been disposed.
          */
@@ -50805,6 +50828,10 @@ declare module BABYLON {
         */
         repeatableContentBlocks: NodeMaterialBlock[];
         /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
          * List of blocks that can block the isReady function for the material
          */
         blockingBlocks: NodeMaterialBlock[];
@@ -50928,6 +50955,7 @@ declare module BABYLON {
                 search: RegExp;
                 replace: string;
             }[];
+            repeatKey?: string;
         }): string;
         /** @hidden */
         _emitFunctionFromInclude(includeName: string, comments: string, options?: {
@@ -51383,6 +51411,13 @@ declare module BABYLON {
         }): this | undefined;
         protected _buildBlock(state: NodeMaterialBuildState): void;
         /**
+         * Add uniforms, samplers and uniform buffers at compilation time
+         * @param state defines the state to update
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to update
+         */
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        /**
          * Add potential fallbacks if shader compilation fails
          * @param mesh defines the mesh to be rendered
          * @param fallbacks defines the current prioritized list of fallbacks
@@ -51546,6 +51581,12 @@ declare module BABYLON {
         wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
+         * Gets an boolean indicating if the current point can be connected to another point
+         * @param connectionPoint defines the other connection point
+         * @returns true if the connection is possible
+         */
+        canConnectTo(connectionPoint: NodeMaterialConnectionPoint): boolean;
+        /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
          * @returns the current connection point
@@ -52032,7 +52073,8 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component
+        * Gets the light input component.
+        * If not defined, all lights will be considered
         */
         readonly light: NodeMaterialConnectionPoint;
         /**
@@ -52049,6 +52091,7 @@ declare module BABYLON {
         readonly specularOutput: NodeMaterialConnectionPoint;
         autoConfigure(): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this | undefined;

+ 36 - 3
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts

@@ -1,5 +1,14 @@
 /// <reference types="react" />
 declare module NODEEDITOR {
+    export class DataStorage {
+        private static _InMemoryStorage;
+        static ReadBoolean(key: string, defaultValue: boolean): boolean;
+        static StoreBoolean(key: string, value: boolean): void;
+        static ReadNumber(key: string, defaultValue: number): number;
+        static StoreNumber(key: string, value: number): void;
+    }
+}
+declare module NODEEDITOR {
     /**
      * Port model
      */
@@ -15,6 +24,7 @@ declare module NODEEDITOR {
         defaultValue: any;
         static idCounter: number;
         constructor(name: string, type?: string);
+        canLinkToPort(port: DefaultPortModel): boolean;
         syncWithNodeMaterialConnectionPoint(connection: BABYLON.NodeMaterialConnectionPoint): void;
         getNodeModel(): DefaultNodeModel;
         link(outPort: DefaultPortModel): LinkModel<import("storm-react-diagrams").LinkModelListener>;
@@ -49,7 +59,6 @@ declare module NODEEDITOR {
     export class LineContainerComponent extends React.Component<ILineContainerComponentProps, {
         isExpanded: boolean;
     }> {
-        private static _InMemoryStorage;
         constructor(props: ILineContainerComponentProps);
         switchExpandedState(): void;
         renderHeader(): JSX.Element;
@@ -459,11 +468,13 @@ declare module NODEEDITOR {
         onSelect?: (value: number | string) => void;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         valuesAreStrings?: boolean;
+        defaultIfNull?: number;
     }
     export class OptionsLineComponent extends React.Component<IOptionsLineComponentProps, {
         value: number | string;
     }> {
         private _localChange;
+        private _getValue;
         constructor(props: IOptionsLineComponentProps);
         shouldComponentUpdate(nextProps: IOptionsLineComponentProps, nextState: {
             value: number;
@@ -545,6 +556,15 @@ declare module NODEEDITOR {
     }
 }
 declare module NODEEDITOR {
+    export class StringTools {
+        /**
+         * Gets the base math type of node material block connection point.
+         * @param type Type to parse.
+         */
+        static GetBaseType(type: BABYLON.NodeMaterialBlockConnectionPointTypes): string;
+    }
+}
+declare module NODEEDITOR {
     interface IInputPropertyTabComponentProps {
         globalState: GlobalState;
         inputNode: InputNodeModel;
@@ -618,8 +638,13 @@ declare module NODEEDITOR {
     interface ILogComponentProps {
         globalState: GlobalState;
     }
+    export class LogEntry {
+        message: string;
+        isError: boolean;
+        constructor(message: string, isError: boolean);
+    }
     export class LogComponent extends React.Component<ILogComponentProps, {
-        logs: string[];
+        logs: LogEntry[];
     }> {
         constructor(props: ILogComponentProps);
         componentWillMount(): void;
@@ -730,6 +755,14 @@ declare module NODEEDITOR {
         build(): void;
         addNodeFromClass(ObjectClass: typeof BABYLON.NodeMaterialBlock): DefaultNodeModel;
         addValueNode(type: string, column?: number, connection?: BABYLON.NodeMaterialConnectionPoint): DefaultNodeModel;
+        private _startX;
+        private _moveInProgress;
+        private _leftWidth;
+        private _rightWidth;
+        onPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        resizeColumns(evt: React.PointerEvent<HTMLDivElement>, forLeft?: boolean): void;
+        buildColumnLayout(): string;
         render(): JSX.Element;
     }
 }
@@ -763,7 +796,7 @@ declare module NODEEDITOR {
         onResetRequiredObservable: BABYLON.Observable<void>;
         onUpdateRequiredObservable: BABYLON.Observable<void>;
         onZoomToFitRequiredObservable: BABYLON.Observable<void>;
-        onLogRequiredObservable: BABYLON.Observable<string>;
+        onLogRequiredObservable: BABYLON.Observable<LogEntry>;
     }
 }
 declare module NODEEDITOR {

文件差異過大導致無法顯示
+ 6 - 6
dist/preview release/nodeEditor/babylon.nodeEditor.js


文件差異過大導致無法顯示
+ 219 - 68
dist/preview release/nodeEditor/babylon.nodeEditor.max.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map


+ 74 - 6
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts

@@ -1,4 +1,13 @@
 /// <reference types="react" />
+declare module "babylonjs-node-editor/dataStorage" {
+    export class DataStorage {
+        private static _InMemoryStorage;
+        static ReadBoolean(key: string, defaultValue: boolean): boolean;
+        static StoreBoolean(key: string, value: boolean): void;
+        static ReadNumber(key: string, defaultValue: number): number;
+        static StoreNumber(key: string, value: number): void;
+    }
+}
 declare module "babylonjs-node-editor/components/diagram/defaultPortModel" {
     import { LinkModel, PortModel } from "storm-react-diagrams";
     import { Nullable } from 'babylonjs/types';
@@ -19,6 +28,7 @@ declare module "babylonjs-node-editor/components/diagram/defaultPortModel" {
         defaultValue: any;
         static idCounter: number;
         constructor(name: string, type?: string);
+        canLinkToPort(port: DefaultPortModel): boolean;
         syncWithNodeMaterialConnectionPoint(connection: NodeMaterialConnectionPoint): void;
         getNodeModel(): DefaultNodeModel;
         link(outPort: DefaultPortModel): LinkModel<import("storm-react-diagrams").LinkModelListener>;
@@ -55,7 +65,6 @@ declare module "babylonjs-node-editor/sharedComponents/lineContainerComponent" {
     export class LineContainerComponent extends React.Component<ILineContainerComponentProps, {
         isExpanded: boolean;
     }> {
-        private static _InMemoryStorage;
         constructor(props: ILineContainerComponentProps);
         switchExpandedState(): void;
         renderHeader(): JSX.Element;
@@ -531,11 +540,13 @@ declare module "babylonjs-node-editor/sharedComponents/optionsLineComponent" {
         onSelect?: (value: number | string) => void;
         onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
         valuesAreStrings?: boolean;
+        defaultIfNull?: number;
     }
     export class OptionsLineComponent extends React.Component<IOptionsLineComponentProps, {
         value: number | string;
     }> {
         private _localChange;
+        private _getValue;
         constructor(props: IOptionsLineComponentProps);
         shouldComponentUpdate(nextProps: IOptionsLineComponentProps, nextState: {
             value: number;
@@ -629,6 +640,16 @@ declare module "babylonjs-node-editor/components/propertyTab/properties/floatPro
         render(): JSX.Element;
     }
 }
+declare module "babylonjs-node-editor/stringTools" {
+    import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
+    export class StringTools {
+        /**
+         * Gets the base math type of node material block connection point.
+         * @param type Type to parse.
+         */
+        static GetBaseType(type: NodeMaterialBlockConnectionPointTypes): string;
+    }
+}
 declare module "babylonjs-node-editor/components/diagram/input/inputNodePropertyComponent" {
     import * as React from "react";
     import { GlobalState } from "babylonjs-node-editor/globalState";
@@ -718,8 +739,13 @@ declare module "babylonjs-node-editor/components/log/logComponent" {
     interface ILogComponentProps {
         globalState: GlobalState;
     }
+    export class LogEntry {
+        message: string;
+        isError: boolean;
+        constructor(message: string, isError: boolean);
+    }
     export class LogComponent extends React.Component<ILogComponentProps, {
-        logs: string[];
+        logs: LogEntry[];
     }> {
         constructor(props: ILogComponentProps);
         componentWillMount(): void;
@@ -852,6 +878,14 @@ declare module "babylonjs-node-editor/graphEditor" {
         build(): void;
         addNodeFromClass(ObjectClass: typeof NodeMaterialBlock): DefaultNodeModel;
         addValueNode(type: string, column?: number, connection?: NodeMaterialConnectionPoint): DefaultNodeModel;
+        private _startX;
+        private _moveInProgress;
+        private _leftWidth;
+        private _rightWidth;
+        onPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        resizeColumns(evt: React.PointerEvent<HTMLDivElement>, forLeft?: boolean): void;
+        buildColumnLayout(): string;
         render(): JSX.Element;
     }
 }
@@ -886,6 +920,7 @@ declare module "babylonjs-node-editor/globalState" {
     import { Nullable } from "babylonjs/types";
     import { Observable } from 'babylonjs/Misc/observable';
     import { DefaultNodeModel } from "babylonjs-node-editor/components/diagram/defaultNodeModel";
+    import { LogEntry } from "babylonjs-node-editor/components/log/logComponent";
     export class GlobalState {
         nodeMaterial?: NodeMaterial;
         hostElement: HTMLElement;
@@ -895,7 +930,7 @@ declare module "babylonjs-node-editor/globalState" {
         onResetRequiredObservable: Observable<void>;
         onUpdateRequiredObservable: Observable<void>;
         onZoomToFitRequiredObservable: Observable<void>;
-        onLogRequiredObservable: Observable<string>;
+        onLogRequiredObservable: Observable<LogEntry>;
     }
 }
 declare module "babylonjs-node-editor/sharedComponents/popup" {
@@ -934,6 +969,15 @@ declare module "babylonjs-node-editor" {
 }
 /// <reference types="react" />
 declare module NODEEDITOR {
+    export class DataStorage {
+        private static _InMemoryStorage;
+        static ReadBoolean(key: string, defaultValue: boolean): boolean;
+        static StoreBoolean(key: string, value: boolean): void;
+        static ReadNumber(key: string, defaultValue: number): number;
+        static StoreNumber(key: string, value: number): void;
+    }
+}
+declare module NODEEDITOR {
     /**
      * Port model
      */
@@ -949,6 +993,7 @@ declare module NODEEDITOR {
         defaultValue: any;
         static idCounter: number;
         constructor(name: string, type?: string);
+        canLinkToPort(port: DefaultPortModel): boolean;
         syncWithNodeMaterialConnectionPoint(connection: BABYLON.NodeMaterialConnectionPoint): void;
         getNodeModel(): DefaultNodeModel;
         link(outPort: DefaultPortModel): LinkModel<import("storm-react-diagrams").LinkModelListener>;
@@ -983,7 +1028,6 @@ declare module NODEEDITOR {
     export class LineContainerComponent extends React.Component<ILineContainerComponentProps, {
         isExpanded: boolean;
     }> {
-        private static _InMemoryStorage;
         constructor(props: ILineContainerComponentProps);
         switchExpandedState(): void;
         renderHeader(): JSX.Element;
@@ -1393,11 +1437,13 @@ declare module NODEEDITOR {
         onSelect?: (value: number | string) => void;
         onPropertyChangedObservable?: BABYLON.Observable<PropertyChangedEvent>;
         valuesAreStrings?: boolean;
+        defaultIfNull?: number;
     }
     export class OptionsLineComponent extends React.Component<IOptionsLineComponentProps, {
         value: number | string;
     }> {
         private _localChange;
+        private _getValue;
         constructor(props: IOptionsLineComponentProps);
         shouldComponentUpdate(nextProps: IOptionsLineComponentProps, nextState: {
             value: number;
@@ -1479,6 +1525,15 @@ declare module NODEEDITOR {
     }
 }
 declare module NODEEDITOR {
+    export class StringTools {
+        /**
+         * Gets the base math type of node material block connection point.
+         * @param type Type to parse.
+         */
+        static GetBaseType(type: BABYLON.NodeMaterialBlockConnectionPointTypes): string;
+    }
+}
+declare module NODEEDITOR {
     interface IInputPropertyTabComponentProps {
         globalState: GlobalState;
         inputNode: InputNodeModel;
@@ -1552,8 +1607,13 @@ declare module NODEEDITOR {
     interface ILogComponentProps {
         globalState: GlobalState;
     }
+    export class LogEntry {
+        message: string;
+        isError: boolean;
+        constructor(message: string, isError: boolean);
+    }
     export class LogComponent extends React.Component<ILogComponentProps, {
-        logs: string[];
+        logs: LogEntry[];
     }> {
         constructor(props: ILogComponentProps);
         componentWillMount(): void;
@@ -1664,6 +1724,14 @@ declare module NODEEDITOR {
         build(): void;
         addNodeFromClass(ObjectClass: typeof BABYLON.NodeMaterialBlock): DefaultNodeModel;
         addValueNode(type: string, column?: number, connection?: BABYLON.NodeMaterialConnectionPoint): DefaultNodeModel;
+        private _startX;
+        private _moveInProgress;
+        private _leftWidth;
+        private _rightWidth;
+        onPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        resizeColumns(evt: React.PointerEvent<HTMLDivElement>, forLeft?: boolean): void;
+        buildColumnLayout(): string;
         render(): JSX.Element;
     }
 }
@@ -1697,7 +1765,7 @@ declare module NODEEDITOR {
         onResetRequiredObservable: BABYLON.Observable<void>;
         onUpdateRequiredObservable: BABYLON.Observable<void>;
         onZoomToFitRequiredObservable: BABYLON.Observable<void>;
-        onLogRequiredObservable: BABYLON.Observable<string>;
+        onLogRequiredObservable: BABYLON.Observable<LogEntry>;
     }
 }
 declare module NODEEDITOR {

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

@@ -1 +1 @@
-{"engineOnly":251951,"sceneOnly":509990,"minGridMaterial":638864,"minStandardMaterial":764875}
+{"engineOnly":252117,"sceneOnly":510292,"minGridMaterial":639202,"minStandardMaterial":765213}

+ 111 - 25
dist/preview release/viewer/babylon.module.d.ts

@@ -4356,6 +4356,10 @@ declare module "babylonjs/Misc/observable" {
         private _eventState;
         private _onObserverAdded;
         /**
+         * Gets the list of observers
+         */
+        readonly observers: Array<Observer<T>>;
+        /**
          * Creates a new observable
          * @param onObserverAdded defines a callback to call when a new observer is added
          */
@@ -10140,7 +10144,7 @@ declare module "babylonjs/Bones/skeleton" {
         private _useTextureToStoreBoneMatrices;
         /**
          * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-         * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+         * Please note that this option is not available if the hardware does not support it
          */
         useTextureToStoreBoneMatrices: boolean;
         private _animationPropertiesOverride;
@@ -10194,9 +10198,10 @@ declare module "babylonjs/Bones/skeleton" {
         getTransformMatrices(mesh: AbstractMesh): Float32Array;
         /**
          * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+         * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
          * @returns a raw texture containing the data
          */
-        getTransformMatrixTexture(): Nullable<RawTexture>;
+        getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture>;
         /**
          * Gets the current hosting scene
          * @returns a scene object
@@ -10479,6 +10484,18 @@ declare module "babylonjs/Morph/morphTargetManager" {
         private _uniqueId;
         private _tempInfluences;
         /**
+         * Gets or sets a boolean indicating if normals must be morphed
+         */
+        enableNormalMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if tangents must be morphed
+         */
+        enableTangentMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if UV must be morphed
+         */
+        enableUVMorphing: boolean;
+        /**
          * Creates a new MorphTargetManager
          * @param scene defines the current scene
          */
@@ -25126,6 +25143,7 @@ declare module "babylonjs/Meshes/abstractMesh" {
     import { IEdgesRenderer } from "babylonjs/Rendering/edgesRenderer";
     import { SolidParticle } from "babylonjs/Particles/solidParticle";
     import { AbstractActionManager } from "babylonjs/Actions/abstractActionManager";
+    import { RawTexture } from "babylonjs/Materials/Textures/rawTexture";
     import { Ray } from "babylonjs/Culling/ray";
     import { Collider } from "babylonjs/Collisions/collider";
     import { TrianglePickingPredicate } from "babylonjs/Culling/ray";
@@ -25466,6 +25484,8 @@ declare module "babylonjs/Meshes/abstractMesh" {
         };
         /** @hidden */
         _bonesTransformMatrices: Nullable<Float32Array>;
+        /** @hidden */
+        _transformMatrixTexture: Nullable<RawTexture>;
         /**
          * Gets or sets a skeleton to apply skining transformations
          * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -35198,6 +35218,10 @@ declare module "babylonjs/Audio/sound" {
          * Defines an optional offset (in seconds) inside the sound file
          */
         offset?: number;
+        /**
+         * If true, URLs will not be required to state the audio file codec to use.
+         */
+        skipCodecCheck?: boolean;
     }
     /**
      * Defines a sound that can be played in the application.
@@ -37238,6 +37262,10 @@ declare module "babylonjs/Behaviors/Meshes/pointerDragBehavior" {
          */
         enabled: boolean;
         /**
+         * If pointer events should start and release the drag (Default: true)
+         */
+        startAndReleaseDragOnPointerEvents: boolean;
+        /**
          * If camera controls should be detached during the drag
          */
         detachCameraControls: boolean;
@@ -42963,7 +42991,6 @@ declare module "babylonjs/Debug/boneAxesViewer" {
     }
 }
 declare module "babylonjs/Debug/debugLayer" {
-    import { Observable } from "babylonjs/Misc/observable";
     import { Scene } from "babylonjs/scene";
     /**
      * Interface used to define scene explorer extensibility option
@@ -43064,15 +43091,11 @@ declare module "babylonjs/Debug/debugLayer" {
         static InspectorURL: string;
         private _scene;
         private BJSINSPECTOR;
+        private _onPropertyChangedObservable?;
         /**
          * Observable triggered when a property is changed through the inspector.
          */
-        onPropertyChangedObservable: Observable<{
-            object: any;
-            property: string;
-            value: any;
-            initialValue: any;
-        }>;
+        readonly onPropertyChangedObservable: any;
         /**
          * Instantiates a new debug layer.
          * The debug layer (aka Inspector) is the go to tool in order to better understand
@@ -48395,9 +48418,9 @@ declare module "babylonjs/Materials/PBR/pbrMaterial" {
         /**
          * Let user defines the brdf lookup texture used for IBL.
          * A default 8bit version is embedded but you could point at :
-         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
          * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
          * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
          */
         environmentBRDFTexture: Nullable<BaseTexture>;
@@ -49500,7 +49523,7 @@ declare module "babylonjs/Layers/effectLayer" {
         /**
          * Gets the rendering group id the layer should render in.
          */
-        readonly renderingGroupId: number;
+        renderingGroupId: number;
         /**
          * An event triggered when the effect layer has been disposed.
          */
@@ -53059,6 +53082,10 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildStateSharedData" {
         */
         repeatableContentBlocks: NodeMaterialBlock[];
         /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
          * List of blocks that can block the isReady function for the material
          */
         blockingBlocks: NodeMaterialBlock[];
@@ -53187,6 +53214,7 @@ declare module "babylonjs/Materials/Node/nodeMaterialBuildState" {
                 search: RegExp;
                 replace: string;
             }[];
+            repeatKey?: string;
         }): string;
         /** @hidden */
         _emitFunctionFromInclude(includeName: string, comments: string, options?: {
@@ -53674,6 +53702,13 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlock" {
         }): this | undefined;
         protected _buildBlock(state: NodeMaterialBuildState): void;
         /**
+         * Add uniforms, samplers and uniform buffers at compilation time
+         * @param state defines the state to update
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to update
+         */
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        /**
          * Add potential fallbacks if shader compilation fails
          * @param mesh defines the mesh to be rendered
          * @param fallbacks defines the current prioritized list of fallbacks
@@ -53845,6 +53880,12 @@ declare module "babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint" {
         wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
+         * Gets an boolean indicating if the current point can be connected to another point
+         * @param connectionPoint defines the other connection point
+         * @returns true if the connection is possible
+         */
+        canConnectTo(connectionPoint: NodeMaterialConnectionPoint): boolean;
+        /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
          * @returns the current connection point
@@ -54407,7 +54448,8 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/lightBlock" {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component
+        * Gets the light input component.
+        * If not defined, all lights will be considered
         */
         readonly light: NodeMaterialConnectionPoint;
         /**
@@ -54424,6 +54466,7 @@ declare module "babylonjs/Materials/Node/Blocks/Dual/lightBlock" {
         readonly specularOutput: NodeMaterialConnectionPoint;
         autoConfigure(): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this | undefined;
@@ -67359,6 +67402,10 @@ declare module BABYLON {
         private _eventState;
         private _onObserverAdded;
         /**
+         * Gets the list of observers
+         */
+        readonly observers: Array<Observer<T>>;
+        /**
          * Creates a new observable
          * @param onObserverAdded defines a callback to call when a new observer is added
          */
@@ -73014,7 +73061,7 @@ declare module BABYLON {
         private _useTextureToStoreBoneMatrices;
         /**
          * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-         * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+         * Please note that this option is not available if the hardware does not support it
          */
         useTextureToStoreBoneMatrices: boolean;
         private _animationPropertiesOverride;
@@ -73068,9 +73115,10 @@ declare module BABYLON {
         getTransformMatrices(mesh: AbstractMesh): Float32Array;
         /**
          * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+         * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
          * @returns a raw texture containing the data
          */
-        getTransformMatrixTexture(): Nullable<RawTexture>;
+        getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture>;
         /**
          * Gets the current hosting scene
          * @returns a scene object
@@ -73344,6 +73392,18 @@ declare module BABYLON {
         private _uniqueId;
         private _tempInfluences;
         /**
+         * Gets or sets a boolean indicating if normals must be morphed
+         */
+        enableNormalMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if tangents must be morphed
+         */
+        enableTangentMorphing: boolean;
+        /**
+         * Gets or sets a boolean indicating if UV must be morphed
+         */
+        enableUVMorphing: boolean;
+        /**
          * Creates a new MorphTargetManager
          * @param scene defines the current scene
          */
@@ -87795,6 +87855,8 @@ declare module BABYLON {
         };
         /** @hidden */
         _bonesTransformMatrices: Nullable<Float32Array>;
+        /** @hidden */
+        _transformMatrixTexture: Nullable<RawTexture>;
         /**
          * Gets or sets a skeleton to apply skining transformations
          * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -97306,6 +97368,10 @@ declare module BABYLON {
          * Defines an optional offset (in seconds) inside the sound file
          */
         offset?: number;
+        /**
+         * If true, URLs will not be required to state the audio file codec to use.
+         */
+        skipCodecCheck?: boolean;
     }
     /**
      * Defines a sound that can be played in the application.
@@ -99237,6 +99303,10 @@ declare module BABYLON {
          */
         enabled: boolean;
         /**
+         * If pointer events should start and release the drag (Default: true)
+         */
+        startAndReleaseDragOnPointerEvents: boolean;
+        /**
          * If camera controls should be detached during the drag
          */
         detachCameraControls: boolean;
@@ -104569,15 +104639,11 @@ declare module BABYLON {
         static InspectorURL: string;
         private _scene;
         private BJSINSPECTOR;
+        private _onPropertyChangedObservable?;
         /**
          * Observable triggered when a property is changed through the inspector.
          */
-        onPropertyChangedObservable: Observable<{
-            object: any;
-            property: string;
-            value: any;
-            initialValue: any;
-        }>;
+        readonly onPropertyChangedObservable: any;
         /**
          * Instantiates a new debug layer.
          * The debug layer (aka Inspector) is the go to tool in order to better understand
@@ -109490,9 +109556,9 @@ declare module BABYLON {
         /**
          * Let user defines the brdf lookup texture used for IBL.
          * A default 8bit version is embedded but you could point at :
-         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+         * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
          * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+         * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
          * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
          */
         environmentBRDFTexture: Nullable<BaseTexture>;
@@ -110512,7 +110578,7 @@ declare module BABYLON {
         /**
          * Gets the rendering group id the layer should render in.
          */
-        readonly renderingGroupId: number;
+        renderingGroupId: number;
         /**
          * An event triggered when the effect layer has been disposed.
          */
@@ -113811,6 +113877,10 @@ declare module BABYLON {
         */
         repeatableContentBlocks: NodeMaterialBlock[];
         /**
+        * List of blocks that can provide a dynamic list of uniforms
+        */
+        dynamicUniformBlocks: NodeMaterialBlock[];
+        /**
          * List of blocks that can block the isReady function for the material
          */
         blockingBlocks: NodeMaterialBlock[];
@@ -113934,6 +114004,7 @@ declare module BABYLON {
                 search: RegExp;
                 replace: string;
             }[];
+            repeatKey?: string;
         }): string;
         /** @hidden */
         _emitFunctionFromInclude(includeName: string, comments: string, options?: {
@@ -114389,6 +114460,13 @@ declare module BABYLON {
         }): this | undefined;
         protected _buildBlock(state: NodeMaterialBuildState): void;
         /**
+         * Add uniforms, samplers and uniform buffers at compilation time
+         * @param state defines the state to update
+         * @param nodeMaterial defines the node material requesting the update
+         * @param defines defines the material defines to update
+         */
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        /**
          * Add potential fallbacks if shader compilation fails
          * @param mesh defines the mesh to be rendered
          * @param fallbacks defines the current prioritized list of fallbacks
@@ -114552,6 +114630,12 @@ declare module BABYLON {
         wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
         private _getTypeLength;
         /**
+         * Gets an boolean indicating if the current point can be connected to another point
+         * @param connectionPoint defines the other connection point
+         * @returns true if the connection is possible
+         */
+        canConnectTo(connectionPoint: NodeMaterialConnectionPoint): boolean;
+        /**
          * Connect this point to another connection point
          * @param connectionPoint defines the other connection point
          * @returns the current connection point
@@ -115038,7 +115122,8 @@ declare module BABYLON {
          */
         readonly worldNormal: NodeMaterialConnectionPoint;
         /**
-        * Gets the light input component
+        * Gets the light input component.
+        * If not defined, all lights will be considered
         */
         readonly light: NodeMaterialConnectionPoint;
         /**
@@ -115055,6 +115140,7 @@ declare module BABYLON {
         readonly specularOutput: NodeMaterialConnectionPoint;
         autoConfigure(): void;
         prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
         bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
         private _injectVertexCode;
         protected _buildBlock(state: NodeMaterialBuildState): this | undefined;

文件差異過大導致無法顯示
+ 27 - 27
dist/preview release/viewer/babylon.viewer.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/viewer/babylon.viewer.max.js


+ 5 - 1
dist/preview release/what's new.md

@@ -21,7 +21,7 @@
 - Method to check if device orientation is available ([TrevorDev](https://github.com/TrevorDev))
 - Added support for sound sprites [Doc](https://doc.babylonjs.com/how_to/playing_sounds_and_music#playing-a-sound-sprite) ([Deltakosh](https://github.com/deltakosh/))
 - Display Oculus Quest controller when using a Quest in WebVR ([TrevorDev](https://github.com/TrevorDev))
-- Fixed Xbox One gamepad controller button schemes ([MackeyK24](https://github.com/MackeyK24/))
+- Added startAndReleaseDragOnPointerEvents property to pointerDragBehavior which can be set to false for custom drag triggering ([TrevorDev](https://github.com/TrevorDev))
 
 ### Engine
 - Morph targets now can morph UV channel as well ([Deltakosh](https://github.com/deltakosh/))
@@ -65,10 +65,14 @@
 - Added `ShaderMaterial.setColor4Array` ([JonathanTron](https://github.com/JonathanTron/))
 - Added `ShaderMaterial.setArray4` ([JonathanTron](https://github.com/JonathanTron/))
 
+### Sounds
+- Added `ISoundOptions.skipCodecCheck` to make `Sound` more flexible with URLs ([nbduke](https://github.com/nbduke))
+
 ### Documentation
 - Added a note on shallow bounding of getBoundingInfo ([tibotiber](https://github.com/tibotiber))
 
 ## Bug fixes
+- Fixed Xbox One gamepad controller button schemes ([MackeyK24](https://github.com/MackeyK24/))
 - Added support for `AnimationGroup` serialization ([Drigax](https://github.com/drigax/))
 - Removing assetContainer from scene will also remove gui layers ([TrevorDev](https://github.com/TrevorDev))
 - A scene's input manager not adding key listeners when the canvas is already focused ([Poolminer](https://github.com/Poolminer))

+ 1 - 1
nodeEditor/src/components/diagram/defaultNodeModel.ts

@@ -63,7 +63,7 @@ export class DefaultNodeModel extends NodeModel {
                 } else {
                     model.addAll(link);
                 }
-            } else {
+            } else if (!connection.isUndefined) {
                 // Create value node for the connection
                 var type = ""
                 if (connection.type == NodeMaterialBlockConnectionPointTypes.Texture) {

+ 8 - 0
nodeEditor/src/components/diagram/defaultPortModel.ts

@@ -26,6 +26,14 @@ export class DefaultPortModel extends PortModel {
         DefaultPortModel.idCounter++;
     }
 
+    canLinkToPort(port: DefaultPortModel): boolean {
+        if (!this.connection || !port.connection) {
+            return true;
+        }
+
+        return this.connection.canConnectTo(port.connection);
+    }
+
     syncWithNodeMaterialConnectionPoint(connection: NodeMaterialConnectionPoint) {
         this.connection = connection;
         this.name = connection.name;

+ 1 - 1
nodeEditor/src/components/diagram/diagram.scss

@@ -1,6 +1,6 @@
 .diagramBlock {
     background: white;
-    width: 200px;
+    width: 100%;
     border: 4px solid black;
 
     &.input {

+ 2 - 23
nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx

@@ -13,6 +13,7 @@ import { TextLineComponent } from '../../../sharedComponents/textLineComponent';
 import { Color3PropertyTabComponent } from '../../propertyTab/properties/color3PropertyTabComponent';
 import { FloatPropertyTabComponent } from '../../propertyTab/properties/floatPropertyTabComponent';
 import { LineContainerComponent } from '../../../sharedComponents/lineContainerComponent';
+import { StringTools } from '../../../stringTools';
 
 interface IInputPropertyTabComponentProps {
     globalState: GlobalState;
@@ -94,32 +95,10 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
             { label: "uv2", value: "uv2" },
         ];
 
-        /**
-         * Gets the base math type of node material block connection point.
-         * @param type Type to parse.
-         */
-        function getBaseType(type: NodeMaterialBlockConnectionPointTypes): string {
-            switch (type) {
-                case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3:
-                case NodeMaterialBlockConnectionPointTypes.Vector4OrColor4:
-                case NodeMaterialBlockConnectionPointTypes.Vector3OrVector4:
-                case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3OrVector4OrColor4:
-                    return "Vector";
-                case NodeMaterialBlockConnectionPointTypes.Color3:
-                case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
-                case NodeMaterialBlockConnectionPointTypes.Color4: {
-                    return "Color";
-                }
-                default: {
-                    return NodeMaterialBlockConnectionPointTypes[type];
-                }
-            }
-        }
-
         return (
             <div>
                 <LineContainerComponent title="GENERAL">
-                    <TextLineComponent label="Type" value={getBaseType(connection.type)} />
+                    <TextLineComponent label="Type" value={StringTools.GetBaseType(connection.type)} />
                 </LineContainerComponent>
                 <LineContainerComponent title="PROPERTIES">
                     <CheckBoxLineComponent label="Is mesh attribute" onSelect={value => {

+ 4 - 1
nodeEditor/src/components/diagram/input/inputNodeWidget.tsx

@@ -7,6 +7,7 @@ import { DefaultPortModel } from '../defaultPortModel';
 import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { Color3 } from 'babylonjs/Maths/math';
+import { StringTools } from '../../../stringTools';
 
 /**
  * GenericNodeWidgetProps
@@ -88,9 +89,11 @@ export class InputNodeWidget extends React.Component<InputNodeWidgetProps> {
 
         let connection = this.props.node!.connection;
         let value = "";
-        let name = port!.name;
+        let name = "";
 
         if (connection) {
+            name = StringTools.GetBaseType(connection.type)
+
             if (connection.isAttribute) {
                 value = "mesh." + connection.name;
             } else if (connection.isWellKnownValue) {

+ 8 - 2
nodeEditor/src/components/diagram/light/lightPropertyTabComponent.tsx

@@ -20,6 +20,8 @@ export class LightPropertyTabComponent extends React.Component<ILightPropertyTab
             return { label: l.name, value: l.name }
         });
 
+        lightOptions.splice(0, 0, { label: "All", value: "" })
+
         return (
             <div>
                 <LineContainerComponent title="GENERAL">
@@ -28,8 +30,12 @@ export class LightPropertyTabComponent extends React.Component<ILightPropertyTab
                 </LineContainerComponent>
 
                 <LineContainerComponent title="PROPERTIES">
-                    <OptionsLineComponent label="Light" noDirectUpdate={true} valuesAreStrings={true} options={lightOptions} target={this.props.node.light} propertyName="name" onSelect={(name: any) => {
-                        this.props.node.light = scene.getLightByName(name);
+                    <OptionsLineComponent label="Light" defaultIfNull={0} noDirectUpdate={true} valuesAreStrings={true} options={lightOptions} target={this.props.node.light} propertyName="name" onSelect={(name: any) => {
+                        if (name === "") {
+                            this.props.node.light = null;
+                        } else {
+                            this.props.node.light = scene.getLightByName(name);
+                        }
                         this.forceUpdate();
                         this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                     }} />

+ 8 - 2
nodeEditor/src/components/log/log.scss

@@ -1,9 +1,11 @@
 #log-console {
     background: #333333;
-    height: 100px;
+    border: #555555 solid 1px;
+    height: 120px;
+    box-sizing: border-box;
     margin: 0;
     padding: 10px;
-    width: calc(100% - 20px); 
+    width: 100%; 
     overflow: hidden;
     overflow-y: auto;
 
@@ -11,5 +13,9 @@
         color: white;
         font-size: 14px;
         font-family: 'Courier New', Courier, monospace;
+
+        &.error {
+            color:red;
+        }
     }
 }

+ 10 - 4
nodeEditor/src/components/log/logComponent.tsx

@@ -9,7 +9,13 @@ interface ILogComponentProps {
     globalState: GlobalState;
 }
 
-export class LogComponent extends React.Component<ILogComponentProps, { logs: string[] }> {
+export class LogEntry {
+    constructor(public message: string, public isError: boolean) {
+
+    }
+}
+
+export class LogComponent extends React.Component<ILogComponentProps, { logs: LogEntry[] }> {
 
     constructor(props: ILogComponentProps) {
         super(props);
@@ -20,7 +26,7 @@ export class LogComponent extends React.Component<ILogComponentProps, { logs: st
     componentWillMount() {
         this.props.globalState.onLogRequiredObservable.add(log => {
             let currentLogs = this.state.logs;
-            currentLogs.push(...log.split("\r\n"));
+            currentLogs.push(log);
 
             this.setState({ logs: currentLogs });
         });
@@ -41,8 +47,8 @@ export class LogComponent extends React.Component<ILogComponentProps, { logs: st
                 {
                     this.state.logs.map((l, i) => {
                         return (
-                            <div key={i} className="log">
-                                {l}
+                            <div key={i} className={"log" + (l.isError ? " error" : "")}>
+                                {l.message}
                             </div>
                         )
                     })

+ 1 - 1
nodeEditor/src/components/nodeList/nodeList.scss

@@ -4,7 +4,7 @@
     margin: 0;
     padding: 0;
     display: grid;
-    width: 200px; 
+    width: 100%; 
     overflow: hidden;
 
     .pane {

+ 1 - 1
nodeEditor/src/components/propertyTab/propertyTab.scss

@@ -11,7 +11,7 @@
         grid-row: 1;
         text-align: center;
         display: grid;
-        grid-template-columns: 30px 1fr 50px;        
+        grid-template-columns: 30px 1fr 20px;        
         -webkit-user-select: none; 
         -moz-user-select: none;   
         -ms-user-select: none;    

+ 65 - 0
nodeEditor/src/dataStorage.ts

@@ -0,0 +1,65 @@
+export class DataStorage {
+    private static _InMemoryStorage: { [key: string]: boolean | number };
+
+    public static ReadBoolean(key: string, defaultValue: boolean): boolean {
+        try {
+            if (this._InMemoryStorage && this._InMemoryStorage[key] !== undefined) {
+                return this._InMemoryStorage[key] as boolean;
+            } else if (typeof (Storage) !== "undefined" && localStorage.getItem(key) !== null) {
+                return localStorage.getItem(key) === "true";
+            } else {
+                return defaultValue;
+            }
+        }
+        catch (e) {
+            this._InMemoryStorage = {};
+            this._InMemoryStorage[key] = defaultValue;
+            return defaultValue;
+        }
+    }
+
+    public static StoreBoolean(key: string, value: boolean) {
+        try {
+            if (this._InMemoryStorage) {
+                this._InMemoryStorage[key] = value;
+            } else if (typeof (Storage) !== "undefined") {
+                localStorage.setItem(key, value ? "true" : "false");
+            }
+        }
+        catch (e) {
+            this._InMemoryStorage = {};
+            this._InMemoryStorage[key] = value;
+        }
+    }
+
+    public static ReadNumber(key: string, defaultValue: number): number {
+        try {
+            if (this._InMemoryStorage && this._InMemoryStorage[key] !== undefined) {
+                return this._InMemoryStorage[key] as number;
+            } else if (typeof (Storage) !== "undefined" && localStorage.getItem(key) !== null) {
+                return parseFloat(localStorage.getItem(key)!);
+            } else {
+                return defaultValue;
+            }
+        }
+        catch (e) {
+            this._InMemoryStorage = {};
+            this._InMemoryStorage[key] = defaultValue;
+            return defaultValue;
+        }
+    }
+
+    public static StoreNumber(key: string, value: number) {
+        try {
+            if (this._InMemoryStorage) {
+                this._InMemoryStorage[key] = value;
+            } else if (typeof (Storage) !== "undefined") {
+                localStorage.setItem(key, value.toString());
+            }
+        }
+        catch (e) {
+            this._InMemoryStorage = {};
+            this._InMemoryStorage[key] = value;
+        }
+    }
+}

+ 2 - 1
nodeEditor/src/globalState.ts

@@ -2,6 +2,7 @@ import { NodeMaterial } from "babylonjs/Materials/Node/nodeMaterial"
 import { Nullable } from "babylonjs/types"
 import { Observable } from 'babylonjs/Misc/observable';
 import { DefaultNodeModel } from './components/diagram/defaultNodeModel';
+import { LogEntry } from './components/log/logComponent';
 
 export class GlobalState {
     nodeMaterial?: NodeMaterial;
@@ -12,5 +13,5 @@ export class GlobalState {
     onResetRequiredObservable = new Observable<void>();
     onUpdateRequiredObservable = new Observable<void>();
     onZoomToFitRequiredObservable = new Observable<void>();
-    onLogRequiredObservable = new Observable<string>();
+    onLogRequiredObservable = new Observable<LogEntry>();
 }

+ 66 - 4
nodeEditor/src/graphEditor.tsx

@@ -24,10 +24,11 @@ import { InputNodeFactory } from './components/diagram/input/inputNodeFactory';
 import { InputNodeModel } from './components/diagram/input/inputNodeModel';
 import { TextureBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/textureBlock';
 import { Vector2, Vector3, Vector4, Matrix, Color3, Color4 } from 'babylonjs/Maths/math';
-import { LogComponent } from './components/log/logComponent';
+import { LogComponent, LogEntry } from './components/log/logComponent';
 import { LightBlock } from 'babylonjs/Materials/Node/Blocks/Dual/lightBlock';
 import { LightNodeModel } from './components/diagram/light/lightNodeModel';
 import { LightNodeFactory } from './components/diagram/light/lightNodeFactory';
+import { DataStorage } from './dataStorage';
 
 require("storm-react-diagrams/dist/style.min.css");
 require("./main.scss");
@@ -179,10 +180,10 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
 
         try {
             this.props.globalState.nodeMaterial.build(true);
-            this.props.globalState.onLogRequiredObservable.notifyObservers("Node material build successful");
+            this.props.globalState.onLogRequiredObservable.notifyObservers(new LogEntry("Node material build successful", false));
         }
         catch (err) {
-            this.props.globalState.onLogRequiredObservable.notifyObservers(err);
+            this.props.globalState.onLogRequiredObservable.notifyObservers(new LogEntry(err, true));
         }
     }
 
@@ -320,16 +321,77 @@ export class GraphEditor extends React.Component<IGraphEditorProps> {
         return localNode;
     }
 
+    private _startX: number;
+    private _moveInProgress: boolean;
+
+    private _leftWidth = DataStorage.ReadNumber("LeftWidth", 200);
+    private _rightWidth = DataStorage.ReadNumber("RightWidth", 300);
+
+    onPointerDown(evt: React.PointerEvent<HTMLDivElement>) {
+        this._startX = evt.clientX;
+        this._moveInProgress = true;
+        evt.currentTarget.setPointerCapture(evt.pointerId);
+    }
+
+    onPointerUp(evt: React.PointerEvent<HTMLDivElement>) {
+        this._moveInProgress = false;
+        evt.currentTarget.releasePointerCapture(evt.pointerId);
+    }
+
+    resizeColumns(evt: React.PointerEvent<HTMLDivElement>, forLeft = true) {
+
+        if (!this._moveInProgress) {
+            return;
+        }
+
+        const deltaX = evt.clientX - this._startX;
+        const rootElement = evt.currentTarget.ownerDocument!.getElementById("node-editor-graph-root") as HTMLDivElement;
+
+        if (forLeft) {
+            this._leftWidth += deltaX;
+            this._leftWidth = Math.max(150, Math.min(400, this._leftWidth));
+            DataStorage.StoreNumber("LeftWidth", this._leftWidth);
+        } else {
+            this._rightWidth -= deltaX;
+            this._rightWidth = Math.max(250, Math.min(500, this._rightWidth));
+            DataStorage.StoreNumber("RightWidth", this._rightWidth);
+        }
+
+        rootElement.style.gridTemplateColumns = this.buildColumnLayout();
+
+        this._startX = evt.clientX;
+    }
+
+    buildColumnLayout() {
+        return `${this._leftWidth}px 4px calc(100% - ${this._leftWidth + 8 + this._rightWidth}px) 4px ${this._rightWidth}px`;
+    }
+
     render() {
         return (
             <Portal globalState={this.props.globalState}>
-                <div id="node-editor-graph-root">
+                <div id="node-editor-graph-root" style={
+                    {
+                        gridTemplateColumns: this.buildColumnLayout()
+                    }
+                }>
                     {/* Node creation menu */}
                     <NodeListComponent globalState={this.props.globalState} onAddValueNode={b => this.addValueNode(b)} onAddNodeFromClass={b => this.addNodeFromClass(b)} />
 
+                    <div id="leftGrab"
+                        onPointerDown={evt => this.onPointerDown(evt)}
+                        onPointerUp={evt => this.onPointerUp(evt)}
+                        onPointerMove={evt => this.resizeColumns(evt)}
+                    ></div>
+
                     {/* The node graph diagram */}
                     <DiagramWidget deleteKeys={[46]} ref={"test"} inverseZoom={true} className="diagram-container" diagramEngine={this._engine} maxNumberPointsPerLink={0} />
 
+                    <div id="rightGrab"
+                        onPointerDown={evt => this.onPointerDown(evt)}
+                        onPointerUp={evt => this.onPointerUp(evt)}
+                        onPointerMove={evt => this.resizeColumns(evt, false)}
+                    ></div>
+
                     {/* Property tab */}
                     <PropertyTabComponent globalState={this.props.globalState} />
 

+ 15 - 4
nodeEditor/src/main.scss

@@ -1,7 +1,6 @@
 #node-editor-graph-root {
     display: grid;
     grid-template-rows: calc(100% - 120px) 120px;
-    grid-template-columns: 200px calc(100% - 500px) 300px;
     height: 100%;
     width: 100%;
     background: #464646;
@@ -13,18 +12,30 @@
     grid-column: 1;
 }
 
+#leftGrab {
+    grid-row: 1 / span 2;
+    grid-column: 2;
+    cursor: ew-resize;
+}
+
+#rightGrab {
+    grid-row: 1 / span 2;
+    grid-column: 4;
+    cursor: ew-resize;
+}
+
 .diagram-container {
     grid-row: 1;
-    grid-column: 2;
+    grid-column: 3;
     background: #222222;
 }
 
 #propertyTab {
     grid-row: 1 / span 2;
-    grid-column: 3;
+    grid-column: 5;
 }
 
 #log-console {
     grid-row: 2;
-    grid-column: 2;
+    grid-column: 3;
 }

+ 3 - 29
nodeEditor/src/sharedComponents/lineContainerComponent.tsx

@@ -1,6 +1,7 @@
 import * as React from "react";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
+import { DataStorage } from '../dataStorage';
 
 
 interface ILineContainerComponentProps {
@@ -10,27 +11,10 @@ interface ILineContainerComponentProps {
 }
 
 export class LineContainerComponent extends React.Component<ILineContainerComponentProps, { isExpanded: boolean }> {
-    private static _InMemoryStorage: { [key: string]: boolean };
-
     constructor(props: ILineContainerComponentProps) {
         super(props);
 
-        let initialState: boolean;
-
-        try {
-            if (LineContainerComponent._InMemoryStorage && LineContainerComponent._InMemoryStorage[this.props.title] !== undefined) {
-                initialState = LineContainerComponent._InMemoryStorage[this.props.title];
-            } else if (typeof (Storage) !== "undefined" && localStorage.getItem(this.props.title) !== null) {
-                initialState = localStorage.getItem(this.props.title) === "true";
-            } else {
-                initialState = !this.props.closed;
-            }
-        }
-        catch (e) {
-            LineContainerComponent._InMemoryStorage = {};
-            LineContainerComponent._InMemoryStorage[this.props.title] = !this.props.closed
-            initialState = !this.props.closed;
-        }
+        let initialState = DataStorage.ReadBoolean(this.props.title, !this.props.closed);
 
         this.state = { isExpanded: initialState };
     }
@@ -38,17 +22,7 @@ export class LineContainerComponent extends React.Component<ILineContainerCompon
     switchExpandedState(): void {
         const newState = !this.state.isExpanded;
 
-        try {
-            if (LineContainerComponent._InMemoryStorage) {
-                LineContainerComponent._InMemoryStorage[this.props.title] = newState;
-            } else if (typeof (Storage) !== "undefined") {
-                localStorage.setItem(this.props.title, newState ? "true" : "false");
-            }
-        }
-        catch (e) {
-            LineContainerComponent._InMemoryStorage = {};
-            LineContainerComponent._InMemoryStorage[this.props.title] = newState;
-        }
+        DataStorage.StoreBoolean(this.props.title, newState);
 
         this.setState({ isExpanded: newState });
     }

+ 7 - 2
nodeEditor/src/sharedComponents/optionsLineComponent.tsx

@@ -17,15 +17,20 @@ interface IOptionsLineComponentProps {
     onSelect?: (value: number | string) => void,
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>,
     valuesAreStrings?: boolean
+    defaultIfNull?: number
 }
 
 export class OptionsLineComponent extends React.Component<IOptionsLineComponentProps, { value: number | string }> {
     private _localChange = false;
 
+    private _getValue(props: IOptionsLineComponentProps) {
+        return props.target ? props.target[props.propertyName] : props.options[props.defaultIfNull || 0];
+    }
+
     constructor(props: IOptionsLineComponentProps) {
         super(props);
 
-        this.state = { value: props.target[props.propertyName] };
+        this.state = { value: this._getValue(props) };
     }
 
     shouldComponentUpdate(nextProps: IOptionsLineComponentProps, nextState: { value: number }) {
@@ -34,7 +39,7 @@ export class OptionsLineComponent extends React.Component<IOptionsLineComponentP
             return true;
         }
 
-        const newValue = nextProps.target[nextProps.propertyName];
+        const newValue = this._getValue(nextProps);
         if (newValue != null && newValue !== nextState.value) {
             nextState.value = newValue;
             return true;

+ 25 - 0
nodeEditor/src/stringTools.ts

@@ -0,0 +1,25 @@
+import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
+
+export class StringTools {
+    /**
+     * Gets the base math type of node material block connection point.
+     * @param type Type to parse.
+     */
+    public static GetBaseType(type: NodeMaterialBlockConnectionPointTypes): string {
+        switch (type) {
+            case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3:
+            case NodeMaterialBlockConnectionPointTypes.Vector4OrColor4:
+            case NodeMaterialBlockConnectionPointTypes.Vector3OrVector4:
+            case NodeMaterialBlockConnectionPointTypes.Vector3OrColor3OrVector4OrColor4:
+                return "Vector";
+            case NodeMaterialBlockConnectionPointTypes.Color3:
+            case NodeMaterialBlockConnectionPointTypes.Color3OrColor4:
+            case NodeMaterialBlockConnectionPointTypes.Color4: {
+                return "Color";
+            }
+            default: {
+                return NodeMaterialBlockConnectionPointTypes[type];
+            }
+        }
+    }
+}

+ 1 - 1
src/Audio/audioSceneComponent.ts

@@ -398,7 +398,7 @@ export class AudioSceneComponent implements ISceneSerializableComponent {
         }
 
         if (listeningCamera && audioEngine.audioContext) {
-            audioEngine.audioContext.listener.setPosition(listeningCamera.position.x, listeningCamera.position.y, listeningCamera.position.z);
+            audioEngine.audioContext.listener.setPosition(listeningCamera.globalPosition.x, listeningCamera.globalPosition.y, listeningCamera.globalPosition.z);
             // for VR cameras
             if (listeningCamera.rigCameras && listeningCamera.rigCameras.length > 0) {
                 listeningCamera = listeningCamera.rigCameras[0];

+ 9 - 12
src/Audio/sound.ts

@@ -68,6 +68,10 @@ export interface ISoundOptions {
      * Defines an optional offset (in seconds) inside the sound file
      */
     offset?: number;
+    /**
+     * If true, URLs will not be required to state the audio file codec to use.
+     */
+    skipCodecCheck?: boolean;
 }
 
 /**
@@ -278,18 +282,11 @@ export class Sound {
                             // If we found a supported format, we load it immediately and stop the loop
                             for (var i = 0; i < urls.length; i++) {
                                 var url = urls[i];
-                                if (url.indexOf(".mp3", url.length - 4) !== -1 && Engine.audioEngine.isMP3supported) {
-                                    codecSupportedFound = true;
-                                }
-                                if (url.indexOf(".ogg", url.length - 4) !== -1 && Engine.audioEngine.isOGGsupported) {
-                                    codecSupportedFound = true;
-                                }
-                                if (url.indexOf(".wav", url.length - 4) !== -1) {
-                                    codecSupportedFound = true;
-                                }
-                                if (url.indexOf("blob:") !== -1) {
-                                    codecSupportedFound = true;
-                                }
+                                codecSupportedFound = (options && options.skipCodecCheck) ||
+                                    (url.indexOf(".mp3", url.length - 4) !== -1 && Engine.audioEngine.isMP3supported) ||
+                                    (url.indexOf(".ogg", url.length - 4) !== -1 && Engine.audioEngine.isOGGsupported) ||
+                                    (url.indexOf(".wav", url.length - 4) !== -1) ||
+                                    (url.indexOf("blob:") !== -1);
                                 if (codecSupportedFound) {
                                     // Loading sound using XHR2
                                     if (!this._streaming) {

+ 7 - 2
src/Behaviors/Meshes/pointerDragBehavior.ts

@@ -82,6 +82,11 @@ export class PointerDragBehavior implements Behavior<AbstractMesh> {
      *  If the drag behavior will react to drag events (Default: true)
      */
     public enabled = true;
+
+    /**
+     * If pointer events should start and release the drag (Default: true)
+     */
+    public startAndReleaseDragOnPointerEvents = true;
     /**
      * If camera controls should be detached during the drag
      */
@@ -171,11 +176,11 @@ export class PointerDragBehavior implements Behavior<AbstractMesh> {
 
             if (pointerInfo.type == PointerEventTypes.POINTERDOWN) {
 
-                if (!this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.pickedPoint && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)) {
+                if (this.startAndReleaseDragOnPointerEvents && !this.dragging && pointerInfo.pickInfo && pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh && pointerInfo.pickInfo.pickedPoint && pointerInfo.pickInfo.ray && pickPredicate(pointerInfo.pickInfo.pickedMesh)) {
                     this._startDrag((<PointerEvent>pointerInfo.event).pointerId, pointerInfo.pickInfo.ray, pointerInfo.pickInfo.pickedPoint);
                 }
             } else if (pointerInfo.type == PointerEventTypes.POINTERUP) {
-                if (this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId) {
+                if (this.startAndReleaseDragOnPointerEvents && this.currentDraggingPointerID == (<PointerEvent>pointerInfo.event).pointerId) {
                     this.releaseDrag();
                 }
             } else if (pointerInfo.type == PointerEventTypes.POINTERMOVE) {

+ 24 - 3
src/Bones/skeleton.ts

@@ -74,7 +74,7 @@ export class Skeleton implements IAnimatable {
     private _useTextureToStoreBoneMatrices = true;
     /**
      * Gets or sets a boolean indicating that bone matrices should be stored as a texture instead of using shader uniforms (default is true).
-     * Please note that this option is not available when needInitialSkinMatrix === true or if the hardware does not support it
+     * Please note that this option is not available if the hardware does not support it
      */
     public get useTextureToStoreBoneMatrices(): boolean {
         return this._useTextureToStoreBoneMatrices;
@@ -118,7 +118,7 @@ export class Skeleton implements IAnimatable {
      * Gets a boolean indicating that the skeleton effectively stores matrices into a texture
      */
     public get isUsingTextureForMatrices() {
-        return this.useTextureToStoreBoneMatrices && this._canUseTextureForBones && !this.needInitialSkinMatrix;
+        return this.useTextureToStoreBoneMatrices && this._canUseTextureForBones;
     }
 
     /**
@@ -189,9 +189,14 @@ export class Skeleton implements IAnimatable {
 
     /**
      * Gets the list of transform matrices to send to shaders inside a texture (one matrix per bone)
+     * @param mesh defines the mesh to use to get the root matrix (if needInitialSkinMatrix === true)
      * @returns a raw texture containing the data
      */
-    public getTransformMatrixTexture(): Nullable<RawTexture> {
+    public getTransformMatrixTexture(mesh: AbstractMesh): Nullable<RawTexture> {
+        if (this.needInitialSkinMatrix && mesh._transformMatrixTexture) {
+            return mesh._transformMatrixTexture;
+        }
+
         return this._transformMatrixTexture;
     }
 
@@ -475,9 +480,25 @@ export class Skeleton implements IAnimatable {
                             bone._updateDifferenceMatrix(Tmp.Matrix[1]);
                         }
                     }
+
+                    if (this.isUsingTextureForMatrices) {
+                        const textureWidth = (this.bones.length + 1) * 4;
+                        if (!mesh._transformMatrixTexture || mesh._transformMatrixTexture.getSize().width !== textureWidth) {
+
+                            if (mesh._transformMatrixTexture) {
+                                mesh._transformMatrixTexture.dispose();
+                            }
+
+                            mesh._transformMatrixTexture = RawTexture.CreateRGBATexture(mesh._bonesTransformMatrices, (this.bones.length + 1) * 4, 1, this._scene, false, false, Constants.TEXTURE_NEAREST_SAMPLINGMODE, Constants.TEXTURETYPE_FLOAT);
+                        }
+                     }
                 }
 
                 this._computeTransformMatrices(mesh._bonesTransformMatrices, poseMatrix);
+
+                if (this.isUsingTextureForMatrices && mesh._transformMatrixTexture) {
+                    mesh._transformMatrixTexture.update(mesh._bonesTransformMatrices);
+                }
             }
         } else {
             if (!this._transformMatrices || this._transformMatrices.length !== 16 * (this.bones.length + 1)) {

+ 20 - 1
src/Debug/debugLayer.ts

@@ -125,10 +125,21 @@ export class DebugLayer {
 
     private BJSINSPECTOR = this._getGlobalInspector();
 
+    private _onPropertyChangedObservable?: Observable<{ object: any, property: string, value: any, initialValue: any }>;
     /**
      * Observable triggered when a property is changed through the inspector.
      */
-    public onPropertyChangedObservable = new Observable<{ object: any, property: string, value: any, initialValue: any }>();
+    public get onPropertyChangedObservable() {
+        if (this.BJSINSPECTOR && this.BJSINSPECTOR.Inspector) {
+            return this.BJSINSPECTOR.Inspector.OnPropertyChangedObservable;
+        }
+
+        if (!this._onPropertyChangedObservable) {
+            this._onPropertyChangedObservable = new Observable<{ object: any, property: string, value: any, initialValue: any }>();
+        }
+
+        return this._onPropertyChangedObservable;
+    }
 
     /**
      * Instantiates a new debug layer.
@@ -153,6 +164,14 @@ export class DebugLayer {
             return;
         }
 
+        if (this._onPropertyChangedObservable) {
+            for (var observer of this._onPropertyChangedObservable!.observers) {
+                this.BJSINSPECTOR.Inspector.OnPropertyChangedObservable.add(observer);
+            }
+            this._onPropertyChangedObservable.clear();
+            this._onPropertyChangedObservable = undefined;
+        }
+
         const userOptions: IInspectorOptions = {
             overlay: false,
             showExplorer: true,

+ 6 - 0
src/Engines/Processors/shaderCodeCursor.ts

@@ -15,6 +15,12 @@ export class ShaderCodeCursor {
         this._lines = [];
 
         for (var line of value) {
+            // Prevent removing line break in macros.
+            if (line[0] === "#") {
+                this._lines.push(line);
+                continue;
+            }
+
             const split = line.split(";");
 
             for (var index = 0; index < split.length; index++) {

+ 3 - 0
src/Layers/effectLayer.ts

@@ -120,6 +120,9 @@ export abstract class EffectLayer {
     public get renderingGroupId(): number {
         return this._effectLayerOptions.renderingGroupId;
     }
+    public set renderingGroupId(renderingGroupId: number) {
+        this._effectLayerOptions.renderingGroupId = renderingGroupId;
+    }
 
     /**
      * An event triggered when the effect layer has been disposed.

+ 1 - 1
src/Lights/Shadows/shadowGenerator.ts

@@ -1001,7 +1001,7 @@ export class ShadowGenerator implements IShadowGenerator {
                 const skeleton = mesh.skeleton;
 
                 if (skeleton.isUsingTextureForMatrices) {
-                    const boneTexture = skeleton.getTransformMatrixTexture();
+                    const boneTexture = skeleton.getTransformMatrixTexture(mesh);
 
                     if (!boneTexture) {
                         return;

+ 71 - 39
src/Materials/Node/Blocks/Dual/lightBlock.ts

@@ -26,7 +26,7 @@ export class LightBlock extends NodeMaterialBlock {
         this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
         this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
 
-        this.registerInput("light", NodeMaterialBlockConnectionPointTypes.Light, false, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("light", NodeMaterialBlockConnectionPointTypes.Light, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("diffuseOutput", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("specularOutput", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
@@ -55,7 +55,8 @@ export class LightBlock extends NodeMaterialBlock {
     }
 
     /**
-    * Gets the light input component
+    * Gets the light input component.
+    * If not defined, all lights will be considered
     */
     public get light(): NodeMaterialConnectionPoint {
         return this._inputs[2];
@@ -89,31 +90,48 @@ export class LightBlock extends NodeMaterialBlock {
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        const scene = mesh.getScene();
+
         if (!this.light.value) {
-            return;
+            MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, nodeMaterial.maxSimultaneousLights);
+        } else {
+            let state = {
+                needNormals: false,
+                needRebuild: false,
+                lightmapMode: false,
+                shadowEnabled: false,
+                specularEnabled: false
+            };
+
+            MaterialHelper.PrepareDefinesForLight(scene, mesh, this.light.value, this._lightId, defines, true, state);
+
+            if (state.needRebuild) {
+                defines.rebuild();
+            }
         }
+    }
 
-        let state = {
-            needNormals: false,
-            needRebuild: false,
-            lightmapMode: false,
-            shadowEnabled: false,
-            specularEnabled: false
-        };
-
-        MaterialHelper.PrepareDefinesForLight(mesh.getScene(), mesh, this.light.value, this._lightId, defines, true, state);
-
-        if (state.needRebuild) {
-            defines.rebuild();
+    public updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        for (var lightIndex = 0; lightIndex < nodeMaterial.maxSimultaneousLights; lightIndex++) {
+            if (!defines["LIGHT" + lightIndex]) {
+                break;
+            }
+            MaterialHelper.PrepareUniformsAndSamplersForLight(lightIndex, state.uniforms, state.samplers, false, state.uniformBuffers);
         }
     }
 
     public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh) {
-        if (!mesh || !this.light.value) {
+        if (!mesh) {
             return;
         }
 
-        MaterialHelper.BindLight(this.light.value, this._lightId, mesh.getScene(), mesh, effect, true, false);
+        const scene = mesh.getScene();
+
+        if (!this.light.value) {
+            MaterialHelper.BindLights(scene, mesh, effect, true, nodeMaterial.maxSimultaneousLights, false);
+        } else {
+            MaterialHelper.BindLight(this.light.value, this._lightId, scene, mesh, effect, true, false);
+        }
     }
 
     private _injectVertexCode(state: NodeMaterialBuildState) {
@@ -145,26 +163,34 @@ export class LightBlock extends NodeMaterialBlock {
         state.sharedData.bindableBlocks.push(this);
         state.sharedData.blocksWithDefines.push(this);
 
-        this._lightId = (state.counters["lightCounter"] !== undefined ? state.counters["lightCounter"] : -1) + 1;
-        state.counters["lightCounter"] = this._lightId;
-
         let comments = `//${this.name}`;
         let worldPos = this.worldPosition;
-        let worldNormal = this.worldNormal;
 
         state._emitFunctionFromInclude("lightsFragmentFunctions", comments, {
             replaceStrings: [
-                { search: /vPositionW/g, replace: "v_" + worldPos.associatedVariableName },
-                { search: /normalW/g, replace: "v_" + worldNormal.associatedVariableName }
+                { search: /vPositionW/g, replace: "v_" + worldPos.associatedVariableName }
             ]
         });
 
-        state._emitFunctionFromInclude(state.supportUniformBuffers ? "lightUboDeclaration" : "lightFragmentDeclaration", comments, {
-            replaceStrings: [{ search: /{X}/g, replace: this._lightId.toString() }]
-        }, this._lightId.toString());
+        if (!this.light.value) { // Emit for all lights
+            state._emitFunctionFromInclude(state.supportUniformBuffers ? "lightUboDeclaration" : "lightFragmentDeclaration", comments, {
+                repeatKey: "maxSimultaneousLights"
+            });
+            this._lightId = 0;
 
-        // Uniforms and samplers
-        MaterialHelper.PrepareUniformsAndSamplersForLight(this._lightId, state.uniforms, state.samplers, undefined, state.uniformBuffers);
+            state.sharedData.dynamicUniformBlocks.push(this);
+        } else {
+
+            this._lightId = (state.counters["lightCounter"] !== undefined ? state.counters["lightCounter"] : -1) + 1;
+            state.counters["lightCounter"] = this._lightId;
+
+            state._emitFunctionFromInclude(state.supportUniformBuffers ? "lightUboDeclaration" : "lightFragmentDeclaration", comments, {
+                replaceStrings: [{ search: /{X}/g, replace: this._lightId.toString() }]
+            }, this._lightId.toString());
+
+            // Uniforms and samplers
+            MaterialHelper.PrepareUniformsAndSamplersForLight(this._lightId, state.uniforms, state.samplers, undefined, state.uniformBuffers);
+        }
 
         // Code
         if (this._lightId === 0) {
@@ -172,25 +198,31 @@ export class LightBlock extends NodeMaterialBlock {
             state.compilationString += `lightingInfo info;\r\n`;
             state.compilationString += `float shadow = 1.;\r\n`;
             state.compilationString += `float glossiness = 0.;\r\n`;
+            state.compilationString += `vec3 diffuseBase = vec3(0., 0., 0.);\r\n`;
+            state.compilationString += `vec3 specularBase = vec3(0., 0., 0.);\r\n`;
+            state.compilationString += `vec3 normalW = v_${this.worldNormal.associatedVariableName};\r\n`;
+        }
+
+        if (this.light.value) {
+            state.compilationString += state._emitCodeFromInclude("lightFragment", comments, {
+                replaceStrings: [
+                    { search: /{X}/g, replace: this._lightId.toString() }
+                ]
+            });
+        } else {
+            state.compilationString += state._emitCodeFromInclude("lightFragment", comments, {
+                repeatKey: "maxSimultaneousLights"
+            });
         }
 
         let diffuseOutput = this.diffuseOutput;
         let specularOutput = this.specularOutput;
 
-        state.compilationString += `vec3 ${diffuseOutput.associatedVariableName} = vec3(0., 0., 0.);\r\n`;
+        state.compilationString += this._declareOutput(diffuseOutput, state) + ` = diffuseBase;\r\n`;
         state.compilationString += `#ifdef SPECULARTERM\r\n`;
-        state.compilationString += `vec3 ${specularOutput.associatedVariableName} = vec3(0., 0., 0.);\r\n`;
+        state.compilationString += this._declareOutput(specularOutput, state) + ` = specularBase;\r\n`;
         state.compilationString += `#endif\r\n`;
 
-        state.compilationString += state._emitCodeFromInclude("lightFragment", comments, {
-            replaceStrings: [
-                { search: /{X}/g, replace: this._lightId.toString() },
-                { search: /diffuseBase/g, replace: diffuseOutput.associatedVariableName },
-                { search: /specularBase/g, replace: specularOutput.associatedVariableName },
-                { search: /normalW/g, replace: "v_" + worldNormal.associatedVariableName }
-            ]
-        });
-
         return this;
     }
 }

+ 4 - 0
src/Materials/Node/nodeMaterial.ts

@@ -571,6 +571,10 @@ export class NodeMaterial extends PushMaterial {
             });
 
             // Uniforms
+            this._sharedData.dynamicUniformBlocks.forEach((b) => {
+                b.updateUniformsAndSamples(this._vertexCompilationState, this, defines);
+            });
+
             let mergedUniforms = this._vertexCompilationState.uniforms;
 
             this._fragmentCompilationState.uniforms.forEach((u) => {

+ 10 - 0
src/Materials/Node/nodeMaterialBlock.ts

@@ -269,6 +269,16 @@ export class NodeMaterialBlock {
     }
 
     /**
+     * Add uniforms, samplers and uniform buffers at compilation time
+     * @param state defines the state to update
+     * @param nodeMaterial defines the node material requesting the update
+     * @param defines defines the material defines to update
+     */
+    public updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        // Do nothing
+    }
+
+    /**
      * Add potential fallbacks if shader compilation fails
      * @param mesh defines the mesh to be rendered
      * @param fallbacks defines the current prioritized list of fallbacks

+ 17 - 6
src/Materials/Node/nodeMaterialBlockConnectionPoint.ts

@@ -291,11 +291,11 @@ export class NodeMaterialConnectionPoint {
     }
 
     /**
-     * Connect this point to another connection point
+     * Gets an boolean indicating if the current point can be connected to another point
      * @param connectionPoint defines the other connection point
-     * @returns the current connection point
+     * @returns true if the connection is possible
      */
-    public connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint {
+    public canConnectTo(connectionPoint: NodeMaterialConnectionPoint) {
         if ((this.type & connectionPoint.type) === 0 && connectionPoint.type !== NodeMaterialBlockConnectionPointTypes.AutoDetect) {
             let fail = true;
             // Check swizzle
@@ -308,9 +308,20 @@ export class NodeMaterialConnectionPoint {
                 }
             }
 
-            if (fail) {
-                throw "Cannot connect two different connection types.";
-            }
+            return !fail;
+        }
+
+        return true;
+    }
+
+    /**
+     * Connect this point to another connection point
+     * @param connectionPoint defines the other connection point
+     * @returns the current connection point
+     */
+    public connectTo(connectionPoint: NodeMaterialConnectionPoint): NodeMaterialConnectionPoint {
+        if (!this.canConnectTo(connectionPoint)) {
+            throw "Cannot connect two different connection types.";
         }
 
         this._endpoints.push(connectionPoint);

+ 5 - 0
src/Materials/Node/nodeMaterialBuildState.ts

@@ -189,7 +189,12 @@ export class NodeMaterialBuildState {
     /** @hidden */
     public _emitCodeFromInclude(includeName: string, comments: string, options?: {
         replaceStrings?: { search: RegExp, replace: string }[],
+        repeatKey?: string
     }) {
+        if (options && options.repeatKey) {
+            return `#include<${includeName}>[0..${options.repeatKey}]\r\n`;
+        }
+
         let code = Effect.IncludesShadersStore[includeName] + "\r\n";
 
         if (this.sharedData.emitComments) {

+ 7 - 0
src/Materials/Node/nodeMaterialBuildStateSharedData.ts

@@ -41,6 +41,11 @@ export class NodeMaterialBuildStateSharedData {
     public repeatableContentBlocks = new Array<NodeMaterialBlock>();
 
     /**
+    * List of blocks that can provide a dynamic list of uniforms
+    */
+    public dynamicUniformBlocks = new Array<NodeMaterialBlock>();
+
+    /**
      * List of blocks that can block the isReady function for the material
      */
     public blockingBlocks = new Array<NodeMaterialBlock>();
@@ -99,6 +104,8 @@ export class NodeMaterialBuildStateSharedData {
         this.variableNames["matricesWeights"] = 0;
         this.variableNames["matricesIndicesExtra"] = 0;
         this.variableNames["matricesWeightsExtra"] = 0;
+        this.variableNames["diffuseBase"] = 0;
+        this.variableNames["specularBase"] = 0;
 
         // Exclude defines
         this.defineNames["MAINUV0"] = 0;

+ 4 - 2
src/Materials/PBR/pbrBaseMaterial.ts

@@ -1475,13 +1475,15 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                 defines.TWOSIDEDLIGHTING = false;
             }
 
+            defines.SPECULARAA = scene.getEngine().getCaps().standardDerivatives && this._enableSpecularAntiAliasing;
+        }
+
+        if (defines._areTexturesDirty || defines._areMiscDirty) {
             defines.ALPHATESTVALUE = `${this._alphaCutOff}${this._alphaCutOff % 1 === 0 ? "." : ""}`;
             defines.PREMULTIPLYALPHA = (this.alphaMode === Constants.ALPHA_PREMULTIPLIED || this.alphaMode === Constants.ALPHA_PREMULTIPLIED_PORTERDUFF);
             defines.ALPHABLEND = this.needAlphaBlendingForMesh(mesh);
             defines.ALPHAFRESNEL = this._useAlphaFresnel || this._useLinearAlphaFresnel;
             defines.LINEARALPHAFRESNEL = this._useLinearAlphaFresnel;
-
-            defines.SPECULARAA = scene.getEngine().getCaps().standardDerivatives && this._enableSpecularAntiAliasing;
         }
 
         if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {

+ 2 - 2
src/Materials/PBR/pbrMaterial.ts

@@ -519,9 +519,9 @@ export class PBRMaterial extends PBRBaseMaterial {
     /**
      * Let user defines the brdf lookup texture used for IBL.
      * A default 8bit version is embedded but you could point at :
-     * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.png
+     * * Default texture: https://assets.babylonjs.com/environments/correlatedMSBRDF_RGBD.png
      * * Default 16bit pixel depth texture: https://assets.babylonjs.com/environments/correlatedMSBRDF.dds
-     * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF.png
+     * * LEGACY Default None correlated https://assets.babylonjs.com/environments/uncorrelatedBRDF_RGBD.png
      * * LEGACY Default None correlated 16bit pixel depth https://assets.babylonjs.com/environments/uncorrelatedBRDF.dds
      */
     @serializeAsTexture()

+ 2 - 2
src/Materials/materialHelper.ts

@@ -719,7 +719,7 @@ export class MaterialHelper {
         for (var i = 0; i < len; i++) {
 
             let light = mesh.lightSources[i];
-            this.BindLight(light, i, scene, mesh, effect, defines, usePhysicalLightFalloff);
+            this.BindLight(light, i, scene, mesh, effect, typeof defines === "boolean" ? defines : defines["SPECULARTERM"], usePhysicalLightFalloff);
         }
     }
 
@@ -762,7 +762,7 @@ export class MaterialHelper {
             const skeleton = mesh.skeleton;
 
             if (skeleton.isUsingTextureForMatrices && effect.getUniformIndex("boneTextureWidth") > -1) {
-                const boneTexture = skeleton.getTransformMatrixTexture();
+                const boneTexture = skeleton.getTransformMatrixTexture(mesh);
                 effect.setTexture("boneSampler", boneTexture);
                 effect.setFloat("boneTextureWidth", 4.0 * (skeleton.bones.length + 1));
             } else {

+ 9 - 0
src/Meshes/abstractMesh.ts

@@ -23,6 +23,7 @@ import { Constants } from "../Engines/constants";
 import { AbstractActionManager } from '../Actions/abstractActionManager';
 import { _MeshCollisionData } from '../Collisions/meshCollisionData';
 import { _DevTools } from '../Misc/devTools';
+import { RawTexture } from '../Materials/Textures/rawTexture';
 
 declare type Ray = import("../Culling/ray").Ray;
 declare type Collider = import("../Collisions/collider").Collider;
@@ -608,6 +609,9 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
     /** @hidden */
     public _bonesTransformMatrices: Nullable<Float32Array> = null;
 
+    /** @hidden */
+    public _transformMatrixTexture: Nullable<RawTexture> = null;
+
     /**
      * Gets or sets a skeleton to apply skining transformations
      * @see http://doc.babylonjs.com/how_to/how_to_use_bones_and_skeletons
@@ -1570,6 +1574,11 @@ export class AbstractMesh extends TransformNode implements IDisposable, ICullabl
         // Skeleton
         this._internalAbstractMeshDataInfo._skeleton = null;
 
+        if (this._transformMatrixTexture) {
+            this._transformMatrixTexture.dispose();
+            this._transformMatrixTexture = null;
+        }
+
         // Intersections in progress
         for (index = 0; index < this._intersectionsInProgress.length; index++) {
             var other = this._intersectionsInProgress[index];

+ 5 - 3
src/Misc/basis.ts

@@ -180,7 +180,6 @@ export class BasisTools {
      * @param transcodeResult the result of transcoding the basis file to load from
      */
     public static LoadTextureFromTranscodeResult(texture: InternalTexture, transcodeResult: TranscodeResult) {
-        texture._invertVScale = texture.invertY;
         for (var i = 0; i < transcodeResult.fileInfo.images.length; i++) {
             var rootImage = transcodeResult.fileInfo.images[i].levels[0];
             texture._invertVScale = texture.invertY;
@@ -189,6 +188,9 @@ export class BasisTools {
                 texture.type = Engine.TEXTURETYPE_UNSIGNED_SHORT_5_6_5;
                 texture.format = Engine.TEXTUREFORMAT_RGB;
 
+                // Fallback is already inverted
+                texture._invertVScale = !texture.invertY;
+
                 if (texture.getEngine().webGLVersion < 2 && (Scalar.Log2(texture.width) % 1 !== 0 || Scalar.Log2(texture.height) % 1 !== 0)) {
                     // Create non power of two texture
                     let source = new InternalTexture(texture.getEngine(), InternalTexture.DATASOURCE_TEMP);
@@ -377,7 +379,7 @@ function workerFunc(): void {
         return info;
     }
 
-    function TranscodeLevel(loadedFile: any, imageIndex: number, levelIndex: number, format: number, convertToRgb565: boolean) {
+    function TranscodeLevel(loadedFile: any, imageIndex: number, levelIndex: number, format: number, convertToRgb565: boolean): Nullable<Uint16Array> {
         var dstSize = loadedFile.getImageTranscodedSizeInBytes(imageIndex, levelIndex, format);
         var dst = new Uint8Array(dstSize);
         if (!loadedFile.transcodeImage(dst, imageIndex, levelIndex, format, 1, 0)) {
@@ -403,7 +405,7 @@ function workerFunc(): void {
      * @param  height aligned height of the image
      * @return the converted pixels
      */
-    function ConvertDxtToRgb565(src: Uint16Array, srcByteOffset: number, width: number, height: number): Uint16Array {
+    function ConvertDxtToRgb565(src: Uint8Array, srcByteOffset: number, width: number, height: number): Uint16Array {
         var c = new Uint16Array(4);
         var dst = new Uint16Array(width * height);
 

+ 9 - 2
src/Misc/observable.ts

@@ -154,6 +154,13 @@ export class Observable<T> {
     private _onObserverAdded: Nullable<(observer: Observer<T>) => void>;
 
     /**
+     * Gets the list of observers
+     */
+    public get observers(): Array<Observer<T>> {
+        return this._observers;
+    }
+
+    /**
      * Creates a new observable
      * @param onObserverAdded defines a callback to call when a new observer is added
      */
@@ -276,8 +283,8 @@ export class Observable<T> {
      * @param observer the observer to move
      */
     public makeObserverTopPriority(observer: Observer<T>) {
-           this._remove(observer);
-           this._observers.unshift(observer);
+        this._remove(observer);
+        this._observers.unshift(observer);
     }
 
     /**

+ 18 - 3
src/Morph/morphTargetManager.ts

@@ -25,6 +25,21 @@ export class MorphTargetManager {
     private _tempInfluences = new Array<number>();
 
     /**
+     * Gets or sets a boolean indicating if normals must be morphed
+     */
+    public enableNormalMorphing = true;
+
+    /**
+     * Gets or sets a boolean indicating if tangents must be morphed
+     */
+    public enableTangentMorphing = true;
+
+    /**
+     * Gets or sets a boolean indicating if UV must be morphed
+     */
+    public enableUVMorphing = true;
+
+    /**
      * Creates a new MorphTargetManager
      * @param scene defines the current scene
      */
@@ -60,21 +75,21 @@ export class MorphTargetManager {
      * Gets a boolean indicating if this manager supports morphing of normals
      */
     public get supportsNormals(): boolean {
-        return this._supportsNormals;
+        return this._supportsNormals && this.enableNormalMorphing;
     }
 
     /**
      * Gets a boolean indicating if this manager supports morphing of tangents
      */
     public get supportsTangents(): boolean {
-        return this._supportsTangents;
+        return this._supportsTangents && this.enableTangentMorphing;
     }
 
     /**
      * Gets a boolean indicating if this manager supports morphing of texture coordinates
      */
     public get supportsUVs(): boolean {
-        return this._supportsUVs;
+        return this._supportsUVs && this.enableUVMorphing;
     }
 
     /**

+ 5 - 1
src/PostProcesses/volumetricLightScatteringPostProcess.ts

@@ -213,7 +213,11 @@ export class VolumetricLightScatteringPostProcess extends PostProcess {
                 { vertexElement: "depth", fragmentElement: "volumetricLightScatteringPass" },
                 attribs,
                 ["world", "mBones", "viewProjection", "diffuseMatrix"],
-                ["diffuseSampler"], join);
+                ["diffuseSampler"],
+                join,
+                undefined, undefined, undefined,
+                { maxSimultaneousMorphTargets: mesh.numBoneInfluencers }
+        );
         }
 
         return this._volumetricLightScatteringPass.isReady();