Browse Source

Merge branch 'master' into FollowCamera_PointersInput

dunk 6 years ago
parent
commit
66ae82f786
55 changed files with 4762 additions and 6054 deletions
  1. 124 87
      Playground/babylon.d.txt
  2. 2 1
      dist/preview release/Oimo.js
  3. 122 84
      dist/preview release/babylon.d.ts
  4. 2 2
      dist/preview release/babylon.js
  5. 239 63
      dist/preview release/babylon.max.js
  6. 1 1
      dist/preview release/babylon.max.js.map
  7. 255 174
      dist/preview release/babylon.module.d.ts
  8. 1 1
      dist/preview release/glTF2Interface/package.json
  9. 2 2
      dist/preview release/gui/babylon.gui.d.ts
  10. 22 7
      dist/preview release/gui/babylon.gui.js
  11. 1 1
      dist/preview release/gui/babylon.gui.js.map
  12. 1 1
      dist/preview release/gui/babylon.gui.min.js
  13. 4 4
      dist/preview release/gui/babylon.gui.module.d.ts
  14. 2 2
      dist/preview release/gui/package.json
  15. 9 28
      dist/preview release/inspector/babylon.inspector.bundle.js
  16. 3334 5336
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  17. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  18. 6 0
      dist/preview release/inspector/babylon.inspector.d.ts
  19. 15 0
      dist/preview release/inspector/babylon.inspector.module.d.ts
  20. 6 6
      dist/preview release/inspector/package.json
  21. 3 3
      dist/preview release/loaders/package.json
  22. 22 7
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  23. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js.map
  24. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  25. 22 7
      dist/preview release/materialsLibrary/babylonjs.materials.js
  26. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.js.map
  27. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  28. 2 2
      dist/preview release/materialsLibrary/package.json
  29. 1 1
      dist/preview release/package.json
  30. 1 1
      dist/preview release/packagesSizeBaseLine.json
  31. 2 2
      dist/preview release/postProcessesLibrary/package.json
  32. 2 2
      dist/preview release/proceduralTexturesLibrary/package.json
  33. 3 3
      dist/preview release/serializers/package.json
  34. 255 174
      dist/preview release/viewer/babylon.module.d.ts
  35. 11 7
      dist/preview release/viewer/babylon.viewer.js
  36. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  37. 3 1
      dist/preview release/what's new.md
  38. 1 1
      gui/src/2D/advancedDynamicTexture.ts
  39. 2 2
      gui/src/2D/controls/button.ts
  40. 31 9
      gui/src/2D/controls/control.ts
  41. 21 1
      inspector/src/components/globalState.ts
  42. 19 4
      inspector/src/components/sceneExplorer/entities/lightTreeItemComponent.tsx
  43. 55 2
      inspector/src/components/sceneExplorer/entities/sceneTreeItemComponent.tsx
  44. 1 1
      inspector/src/components/sceneExplorer/sceneExplorer.scss
  45. 1 1
      inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx
  46. 17 1
      inspector/src/inspector.ts
  47. 1 1
      materialsLibrary/src/terrain/terrain.fragment.fx
  48. 28 7
      materialsLibrary/src/terrain/terrainMaterial.ts
  49. 1 1
      package.json
  50. 8 2
      src/Cameras/VR/vrExperienceHelper.ts
  51. 21 2
      src/Engines/engine.ts
  52. 1 1
      src/Gizmos/gizmo.ts
  53. 2 1
      src/Gizmos/index.ts
  54. 70 0
      src/Gizmos/lightGizmo.ts
  55. 1 1
      src/Lights/shadowLight.ts

+ 124 - 87
Playground/babylon.d.txt

@@ -7363,6 +7363,87 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * A multi-material is used to apply different materials to different parts of the same object without the need of
+     * separate meshes. This can be use to improve performances.
+     * @see http://doc.babylonjs.com/how_to/multi_materials
+     */
+    export class MultiMaterial extends Material {
+        private _subMaterials;
+        /**
+         * Gets or Sets the list of Materials used within the multi material.
+         * They need to be ordered according to the submeshes order in the associated mesh
+         */
+        subMaterials: Nullable<Material>[];
+        /**
+         * Function used to align with Node.getChildren()
+         * @returns the list of Materials used within the multi material
+         */
+        getChildren(): Nullable<Material>[];
+        /**
+         * Instantiates a new Multi Material
+         * A multi-material is used to apply different materials to different parts of the same object without the need of
+         * separate meshes. This can be use to improve performances.
+         * @see http://doc.babylonjs.com/how_to/multi_materials
+         * @param name Define the name in the scene
+         * @param scene Define the scene the material belongs to
+         */
+        constructor(name: string, scene: Scene);
+        private _hookArray;
+        /**
+         * Get one of the submaterial by its index in the submaterials array
+         * @param index The index to look the sub material at
+         * @returns The Material if the index has been defined
+         */
+        getSubMaterial(index: number): Nullable<Material>;
+        /**
+         * Get the list of active textures for the whole sub materials list.
+         * @returns All the textures that will be used during the rendering
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
+         * Gets the current class name of the material e.g. "MultiMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Checks if the material is ready to render the requested sub mesh
+         * @param mesh Define the mesh the submesh belongs to
+         * @param subMesh Define the sub mesh to look readyness for
+         * @param useInstances Define whether or not the material is used with instances
+         * @returns true if ready, otherwise false
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
+        /**
+         * Clones the current material and its related sub materials
+         * @param name Define the name of the newly cloned material
+         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
+         * @returns the cloned material
+         */
+        clone(name: string, cloneChildren?: boolean): MultiMaterial;
+        /**
+         * Serializes the materials into a JSON representation.
+         * @returns the JSON representation
+         */
+        serialize(): any;
+        /**
+         * Dispose the material and release its associated resources
+         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
+         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
+         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
+        /**
+         * Creates a MultiMaterial from parsed MultiMaterial data.
+         * @param parsedMultiMaterial defines parsed MultiMaterial data.
+         * @param scene defines the hosting scene
+         * @returns a new MultiMaterial
+         */
+        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
+    }
+}
+declare module BABYLON {
+    /**
      * Class used to represent data loading progression
      */
     export class SceneLoaderFlags {
@@ -8582,7 +8663,7 @@ declare module BABYLON {
         getAbsolutePosition(): Vector3;
         /**
          * Sets the ShadowLight direction toward the passed target.
-         * @param target The point tot target in local space
+         * @param target The point to target in local space
          * @returns the updated ShadowLight direction
          */
         setDirectionToTarget(target: Vector3): Vector3;
@@ -19806,9 +19887,10 @@ declare module BABYLON {
          * @param allow32BitsIndices when the sum of the vertices > 64k, this must be set to true
          * @param meshSubclass when set, vertices inserted into this Mesh.  Meshes can then be merged into a Mesh sub-class.
          * @param subdivideWithSubMeshes when true (false default), subdivide mesh to his subMesh array with meshes source.
+         * @param multiMultiMaterials when true (false default), subdivide mesh and accept multiple multi materials, ignores subdivideWithSubMeshes.
          * @returns a new mesh
          */
-        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean): Nullable<Mesh>;
+        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean, multiMultiMaterials?: boolean): Nullable<Mesh>;
         /** @hidden */
         addInstance(instance: InstancedMesh): void;
         /** @hidden */
@@ -20372,87 +20454,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * A multi-material is used to apply different materials to different parts of the same object without the need of
-     * separate meshes. This can be use to improve performances.
-     * @see http://doc.babylonjs.com/how_to/multi_materials
-     */
-    export class MultiMaterial extends Material {
-        private _subMaterials;
-        /**
-         * Gets or Sets the list of Materials used within the multi material.
-         * They need to be ordered according to the submeshes order in the associated mesh
-         */
-        subMaterials: Nullable<Material>[];
-        /**
-         * Function used to align with Node.getChildren()
-         * @returns the list of Materials used within the multi material
-         */
-        getChildren(): Nullable<Material>[];
-        /**
-         * Instantiates a new Multi Material
-         * A multi-material is used to apply different materials to different parts of the same object without the need of
-         * separate meshes. This can be use to improve performances.
-         * @see http://doc.babylonjs.com/how_to/multi_materials
-         * @param name Define the name in the scene
-         * @param scene Define the scene the material belongs to
-         */
-        constructor(name: string, scene: Scene);
-        private _hookArray;
-        /**
-         * Get one of the submaterial by its index in the submaterials array
-         * @param index The index to look the sub material at
-         * @returns The Material if the index has been defined
-         */
-        getSubMaterial(index: number): Nullable<Material>;
-        /**
-         * Get the list of active textures for the whole sub materials list.
-         * @returns All the textures that will be used during the rendering
-         */
-        getActiveTextures(): BaseTexture[];
-        /**
-         * Gets the current class name of the material e.g. "MultiMaterial"
-         * Mainly use in serialization.
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Checks if the material is ready to render the requested sub mesh
-         * @param mesh Define the mesh the submesh belongs to
-         * @param subMesh Define the sub mesh to look readyness for
-         * @param useInstances Define whether or not the material is used with instances
-         * @returns true if ready, otherwise false
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
-        /**
-         * Clones the current material and its related sub materials
-         * @param name Define the name of the newly cloned material
-         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
-         * @returns the cloned material
-         */
-        clone(name: string, cloneChildren?: boolean): MultiMaterial;
-        /**
-         * Serializes the materials into a JSON representation.
-         * @returns the JSON representation
-         */
-        serialize(): any;
-        /**
-         * Dispose the material and release its associated resources
-         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
-         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
-         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
-         */
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
-        /**
-         * Creates a MultiMaterial from parsed MultiMaterial data.
-         * @param parsedMultiMaterial defines parsed MultiMaterial data.
-         * @param scene defines the hosting scene
-         * @returns a new MultiMaterial
-         */
-        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class for submeshes
      */
     export class BaseSubMesh {
@@ -26512,6 +26513,15 @@ declare module BABYLON {
          */
         switchFullscreen(requestPointerLock: boolean): void;
         /**
+         * Enters full screen mode
+         * @param requestPointerLock defines if a pointer lock should be requested from the user
+         */
+        enterFullscreen(requestPointerLock: boolean): void;
+        /**
+         * Exits full screen mode
+         */
+        exitFullscreen(): void;
+        /**
          * Clear the current render buffer or the current render target (if any is set up)
          * @param color defines the color to use
          * @param backBuffer defines if the back buffer must be cleared
@@ -37925,6 +37935,11 @@ declare module BABYLON {
         readonly vrDeviceOrientationCamera: Nullable<VRDeviceOrientationFreeCamera>;
         private readonly _teleportationRequestInitiated;
         /**
+         * Defines wether or not Pointer lock should be requested when switching to
+         * full screen.
+         */
+        requestPointerLockOnFullScreen: boolean;
+        /**
          * Instantiates a VRExperienceHelper.
          * Helps to quickly add VR support to an existing scene.
          * @param scene The scene the VRExperienceHelper belongs to.
@@ -38794,8 +38809,7 @@ declare module BABYLON {
         gizmoLayer: UtilityLayerRenderer;
         /**
          * The root mesh of the gizmo
-         */
-        protected _rootMesh: Mesh;
+         */
rootMesh: Mesh;
         private _attachedMesh;
         /**
          * Ratio for the scale of the gizmo (Default: 1)
@@ -40806,6 +40820,29 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /**
+     * Gizmo that enables viewing a light
+     */
+    export class LightGizmo extends Gizmo {
+        private _box;
+        /**
+         * Creates a LightGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _light;
+        /**
+         * The light that the gizmo is attached to
+         */
+        light: Nullable<Light>;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+    }
+}
+declare module BABYLON {
     /** @hidden */
     export var backgroundFragmentDeclaration: {
         name: string;
@@ -54145,7 +54182,7 @@ declare module BABYLON.GUI {
         /** @hidden */
processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
onPointerMove(target: Control, coordinates: BABYLON.Vector2): void;
         /** @hidden */
onPointerEnter(target: Control): boolean;
-        /** @hidden */
onPointerOut(target: Control): void;
+        /** @hidden */
onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         /** @hidden */
forcePointerUp(pointerId?: BABYLON.Nullable<number>): void;
@@ -54619,7 +54656,7 @@ declare module BABYLON.GUI {
         protected _getTypeName(): string;
         /** @hidden */
processPicking(x: number, y: number, type: number, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
onPointerEnter(target: Control): boolean;
-        /** @hidden */
onPointerOut(target: Control): void;
+        /** @hidden */
onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
         /**

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


+ 122 - 84
dist/preview release/babylon.d.ts

@@ -7446,6 +7446,87 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * A multi-material is used to apply different materials to different parts of the same object without the need of
+     * separate meshes. This can be use to improve performances.
+     * @see http://doc.babylonjs.com/how_to/multi_materials
+     */
+    export class MultiMaterial extends Material {
+        private _subMaterials;
+        /**
+         * Gets or Sets the list of Materials used within the multi material.
+         * They need to be ordered according to the submeshes order in the associated mesh
+         */
+        subMaterials: Nullable<Material>[];
+        /**
+         * Function used to align with Node.getChildren()
+         * @returns the list of Materials used within the multi material
+         */
+        getChildren(): Nullable<Material>[];
+        /**
+         * Instantiates a new Multi Material
+         * A multi-material is used to apply different materials to different parts of the same object without the need of
+         * separate meshes. This can be use to improve performances.
+         * @see http://doc.babylonjs.com/how_to/multi_materials
+         * @param name Define the name in the scene
+         * @param scene Define the scene the material belongs to
+         */
+        constructor(name: string, scene: Scene);
+        private _hookArray;
+        /**
+         * Get one of the submaterial by its index in the submaterials array
+         * @param index The index to look the sub material at
+         * @returns The Material if the index has been defined
+         */
+        getSubMaterial(index: number): Nullable<Material>;
+        /**
+         * Get the list of active textures for the whole sub materials list.
+         * @returns All the textures that will be used during the rendering
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
+         * Gets the current class name of the material e.g. "MultiMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Checks if the material is ready to render the requested sub mesh
+         * @param mesh Define the mesh the submesh belongs to
+         * @param subMesh Define the sub mesh to look readyness for
+         * @param useInstances Define whether or not the material is used with instances
+         * @returns true if ready, otherwise false
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
+        /**
+         * Clones the current material and its related sub materials
+         * @param name Define the name of the newly cloned material
+         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
+         * @returns the cloned material
+         */
+        clone(name: string, cloneChildren?: boolean): MultiMaterial;
+        /**
+         * Serializes the materials into a JSON representation.
+         * @returns the JSON representation
+         */
+        serialize(): any;
+        /**
+         * Dispose the material and release its associated resources
+         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
+         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
+         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
+        /**
+         * Creates a MultiMaterial from parsed MultiMaterial data.
+         * @param parsedMultiMaterial defines parsed MultiMaterial data.
+         * @param scene defines the hosting scene
+         * @returns a new MultiMaterial
+         */
+        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
+    }
+}
+declare module BABYLON {
+    /**
      * Class used to represent data loading progression
      */
     export class SceneLoaderFlags {
@@ -8694,7 +8775,7 @@ declare module BABYLON {
         getAbsolutePosition(): Vector3;
         /**
          * Sets the ShadowLight direction toward the passed target.
-         * @param target The point tot target in local space
+         * @param target The point to target in local space
          * @returns the updated ShadowLight direction
          */
         setDirectionToTarget(target: Vector3): Vector3;
@@ -20104,9 +20185,10 @@ declare module BABYLON {
          * @param allow32BitsIndices when the sum of the vertices > 64k, this must be set to true
          * @param meshSubclass when set, vertices inserted into this Mesh.  Meshes can then be merged into a Mesh sub-class.
          * @param subdivideWithSubMeshes when true (false default), subdivide mesh to his subMesh array with meshes source.
+         * @param multiMultiMaterials when true (false default), subdivide mesh and accept multiple multi materials, ignores subdivideWithSubMeshes.
          * @returns a new mesh
          */
-        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean): Nullable<Mesh>;
+        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean, multiMultiMaterials?: boolean): Nullable<Mesh>;
         /** @hidden */
         addInstance(instance: InstancedMesh): void;
         /** @hidden */
@@ -20675,87 +20757,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * A multi-material is used to apply different materials to different parts of the same object without the need of
-     * separate meshes. This can be use to improve performances.
-     * @see http://doc.babylonjs.com/how_to/multi_materials
-     */
-    export class MultiMaterial extends Material {
-        private _subMaterials;
-        /**
-         * Gets or Sets the list of Materials used within the multi material.
-         * They need to be ordered according to the submeshes order in the associated mesh
-         */
-        subMaterials: Nullable<Material>[];
-        /**
-         * Function used to align with Node.getChildren()
-         * @returns the list of Materials used within the multi material
-         */
-        getChildren(): Nullable<Material>[];
-        /**
-         * Instantiates a new Multi Material
-         * A multi-material is used to apply different materials to different parts of the same object without the need of
-         * separate meshes. This can be use to improve performances.
-         * @see http://doc.babylonjs.com/how_to/multi_materials
-         * @param name Define the name in the scene
-         * @param scene Define the scene the material belongs to
-         */
-        constructor(name: string, scene: Scene);
-        private _hookArray;
-        /**
-         * Get one of the submaterial by its index in the submaterials array
-         * @param index The index to look the sub material at
-         * @returns The Material if the index has been defined
-         */
-        getSubMaterial(index: number): Nullable<Material>;
-        /**
-         * Get the list of active textures for the whole sub materials list.
-         * @returns All the textures that will be used during the rendering
-         */
-        getActiveTextures(): BaseTexture[];
-        /**
-         * Gets the current class name of the material e.g. "MultiMaterial"
-         * Mainly use in serialization.
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Checks if the material is ready to render the requested sub mesh
-         * @param mesh Define the mesh the submesh belongs to
-         * @param subMesh Define the sub mesh to look readyness for
-         * @param useInstances Define whether or not the material is used with instances
-         * @returns true if ready, otherwise false
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
-        /**
-         * Clones the current material and its related sub materials
-         * @param name Define the name of the newly cloned material
-         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
-         * @returns the cloned material
-         */
-        clone(name: string, cloneChildren?: boolean): MultiMaterial;
-        /**
-         * Serializes the materials into a JSON representation.
-         * @returns the JSON representation
-         */
-        serialize(): any;
-        /**
-         * Dispose the material and release its associated resources
-         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
-         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
-         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
-         */
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
-        /**
-         * Creates a MultiMaterial from parsed MultiMaterial data.
-         * @param parsedMultiMaterial defines parsed MultiMaterial data.
-         * @param scene defines the hosting scene
-         * @returns a new MultiMaterial
-         */
-        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class for submeshes
      */
     export class BaseSubMesh {
@@ -26945,6 +26946,15 @@ declare module BABYLON {
          */
         switchFullscreen(requestPointerLock: boolean): void;
         /**
+         * Enters full screen mode
+         * @param requestPointerLock defines if a pointer lock should be requested from the user
+         */
+        enterFullscreen(requestPointerLock: boolean): void;
+        /**
+         * Exits full screen mode
+         */
+        exitFullscreen(): void;
+        /**
          * Clear the current render buffer or the current render target (if any is set up)
          * @param color defines the color to use
          * @param backBuffer defines if the back buffer must be cleared
@@ -38526,6 +38536,11 @@ declare module BABYLON {
         readonly vrDeviceOrientationCamera: Nullable<VRDeviceOrientationFreeCamera>;
         private readonly _teleportationRequestInitiated;
         /**
+         * Defines wether or not Pointer lock should be requested when switching to
+         * full screen.
+         */
+        requestPointerLockOnFullScreen: boolean;
+        /**
          * Instantiates a VRExperienceHelper.
          * Helps to quickly add VR support to an existing scene.
          * @param scene The scene the VRExperienceHelper belongs to.
@@ -39406,7 +39421,7 @@ declare module BABYLON {
         /**
          * The root mesh of the gizmo
          */
-        protected _rootMesh: Mesh;
+        _rootMesh: Mesh;
         private _attachedMesh;
         /**
          * Ratio for the scale of the gizmo (Default: 1)
@@ -41439,6 +41454,29 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /**
+     * Gizmo that enables viewing a light
+     */
+    export class LightGizmo extends Gizmo {
+        private _box;
+        /**
+         * Creates a LightGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _light;
+        /**
+         * The light that the gizmo is attached to
+         */
+        light: Nullable<Light>;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+    }
+}
+declare module BABYLON {
     /** @hidden */
     export var backgroundFragmentDeclaration: {
         name: string;

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


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


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


+ 255 - 174
dist/preview release/babylon.module.d.ts

@@ -7489,6 +7489,93 @@ declare module "babylonjs/Misc/smartArray" {
         concatWithNoDuplicate(array: any): void;
     }
 }
+declare module "babylonjs/Materials/multiMaterial" {
+    import { Nullable } from "babylonjs/types";
+    import { Scene } from "babylonjs/scene";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { BaseSubMesh } from "babylonjs/Meshes/subMesh";
+    import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
+    import { Material } from "babylonjs/Materials/material";
+    /**
+     * A multi-material is used to apply different materials to different parts of the same object without the need of
+     * separate meshes. This can be use to improve performances.
+     * @see http://doc.babylonjs.com/how_to/multi_materials
+     */
+    export class MultiMaterial extends Material {
+        private _subMaterials;
+        /**
+         * Gets or Sets the list of Materials used within the multi material.
+         * They need to be ordered according to the submeshes order in the associated mesh
+         */
+        subMaterials: Nullable<Material>[];
+        /**
+         * Function used to align with Node.getChildren()
+         * @returns the list of Materials used within the multi material
+         */
+        getChildren(): Nullable<Material>[];
+        /**
+         * Instantiates a new Multi Material
+         * A multi-material is used to apply different materials to different parts of the same object without the need of
+         * separate meshes. This can be use to improve performances.
+         * @see http://doc.babylonjs.com/how_to/multi_materials
+         * @param name Define the name in the scene
+         * @param scene Define the scene the material belongs to
+         */
+        constructor(name: string, scene: Scene);
+        private _hookArray;
+        /**
+         * Get one of the submaterial by its index in the submaterials array
+         * @param index The index to look the sub material at
+         * @returns The Material if the index has been defined
+         */
+        getSubMaterial(index: number): Nullable<Material>;
+        /**
+         * Get the list of active textures for the whole sub materials list.
+         * @returns All the textures that will be used during the rendering
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
+         * Gets the current class name of the material e.g. "MultiMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Checks if the material is ready to render the requested sub mesh
+         * @param mesh Define the mesh the submesh belongs to
+         * @param subMesh Define the sub mesh to look readyness for
+         * @param useInstances Define whether or not the material is used with instances
+         * @returns true if ready, otherwise false
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
+        /**
+         * Clones the current material and its related sub materials
+         * @param name Define the name of the newly cloned material
+         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
+         * @returns the cloned material
+         */
+        clone(name: string, cloneChildren?: boolean): MultiMaterial;
+        /**
+         * Serializes the materials into a JSON representation.
+         * @returns the JSON representation
+         */
+        serialize(): any;
+        /**
+         * Dispose the material and release its associated resources
+         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
+         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
+         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
+        /**
+         * Creates a MultiMaterial from parsed MultiMaterial data.
+         * @param parsedMultiMaterial defines parsed MultiMaterial data.
+         * @param scene defines the hosting scene
+         * @returns a new MultiMaterial
+         */
+        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
+    }
+}
 declare module "babylonjs/Loading/sceneLoaderFlags" {
     /**
      * Class used to represent data loading progression
@@ -8779,7 +8866,7 @@ declare module "babylonjs/Lights/shadowLight" {
         getAbsolutePosition(): Vector3;
         /**
          * Sets the ShadowLight direction toward the passed target.
-         * @param target The point tot target in local space
+         * @param target The point to target in local space
          * @returns the updated ShadowLight direction
          */
         setDirectionToTarget(target: Vector3): Vector3;
@@ -20603,9 +20690,10 @@ declare module "babylonjs/Meshes/mesh" {
          * @param allow32BitsIndices when the sum of the vertices > 64k, this must be set to true
          * @param meshSubclass when set, vertices inserted into this Mesh.  Meshes can then be merged into a Mesh sub-class.
          * @param subdivideWithSubMeshes when true (false default), subdivide mesh to his subMesh array with meshes source.
+         * @param multiMultiMaterials when true (false default), subdivide mesh and accept multiple multi materials, ignores subdivideWithSubMeshes.
          * @returns a new mesh
          */
-        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean): Nullable<Mesh>;
+        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean, multiMultiMaterials?: boolean): Nullable<Mesh>;
         /** @hidden */
         addInstance(instance: InstancedMesh): void;
         /** @hidden */
@@ -21187,93 +21275,6 @@ declare module "babylonjs/Materials/material" {
         static Parse(parsedMaterial: any, scene: Scene, rootUrl: string): any;
     }
 }
-declare module "babylonjs/Materials/multiMaterial" {
-    import { Nullable } from "babylonjs/types";
-    import { Scene } from "babylonjs/scene";
-    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { BaseSubMesh } from "babylonjs/Meshes/subMesh";
-    import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
-    import { Material } from "babylonjs/Materials/material";
-    /**
-     * A multi-material is used to apply different materials to different parts of the same object without the need of
-     * separate meshes. This can be use to improve performances.
-     * @see http://doc.babylonjs.com/how_to/multi_materials
-     */
-    export class MultiMaterial extends Material {
-        private _subMaterials;
-        /**
-         * Gets or Sets the list of Materials used within the multi material.
-         * They need to be ordered according to the submeshes order in the associated mesh
-         */
-        subMaterials: Nullable<Material>[];
-        /**
-         * Function used to align with Node.getChildren()
-         * @returns the list of Materials used within the multi material
-         */
-        getChildren(): Nullable<Material>[];
-        /**
-         * Instantiates a new Multi Material
-         * A multi-material is used to apply different materials to different parts of the same object without the need of
-         * separate meshes. This can be use to improve performances.
-         * @see http://doc.babylonjs.com/how_to/multi_materials
-         * @param name Define the name in the scene
-         * @param scene Define the scene the material belongs to
-         */
-        constructor(name: string, scene: Scene);
-        private _hookArray;
-        /**
-         * Get one of the submaterial by its index in the submaterials array
-         * @param index The index to look the sub material at
-         * @returns The Material if the index has been defined
-         */
-        getSubMaterial(index: number): Nullable<Material>;
-        /**
-         * Get the list of active textures for the whole sub materials list.
-         * @returns All the textures that will be used during the rendering
-         */
-        getActiveTextures(): BaseTexture[];
-        /**
-         * Gets the current class name of the material e.g. "MultiMaterial"
-         * Mainly use in serialization.
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Checks if the material is ready to render the requested sub mesh
-         * @param mesh Define the mesh the submesh belongs to
-         * @param subMesh Define the sub mesh to look readyness for
-         * @param useInstances Define whether or not the material is used with instances
-         * @returns true if ready, otherwise false
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
-        /**
-         * Clones the current material and its related sub materials
-         * @param name Define the name of the newly cloned material
-         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
-         * @returns the cloned material
-         */
-        clone(name: string, cloneChildren?: boolean): MultiMaterial;
-        /**
-         * Serializes the materials into a JSON representation.
-         * @returns the JSON representation
-         */
-        serialize(): any;
-        /**
-         * Dispose the material and release its associated resources
-         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
-         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
-         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
-         */
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
-        /**
-         * Creates a MultiMaterial from parsed MultiMaterial data.
-         * @param parsedMultiMaterial defines parsed MultiMaterial data.
-         * @param scene defines the hosting scene
-         * @returns a new MultiMaterial
-         */
-        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
-    }
-}
 declare module "babylonjs/Meshes/subMesh" {
     import { Nullable, IndicesArray, DeepImmutable } from "babylonjs/types";
     import { Matrix, Vector3, Plane } from "babylonjs/Maths/math";
@@ -27625,6 +27626,15 @@ declare module "babylonjs/Engines/engine" {
          */
         switchFullscreen(requestPointerLock: boolean): void;
         /**
+         * Enters full screen mode
+         * @param requestPointerLock defines if a pointer lock should be requested from the user
+         */
+        enterFullscreen(requestPointerLock: boolean): void;
+        /**
+         * Exits full screen mode
+         */
+        exitFullscreen(): void;
+        /**
          * Clear the current render buffer or the current render target (if any is set up)
          * @param color defines the color to use
          * @param backBuffer defines if the back buffer must be cleared
@@ -39749,6 +39759,11 @@ declare module "babylonjs/Cameras/VR/vrExperienceHelper" {
         readonly vrDeviceOrientationCamera: Nullable<VRDeviceOrientationFreeCamera>;
         private readonly _teleportationRequestInitiated;
         /**
+         * Defines wether or not Pointer lock should be requested when switching to
+         * full screen.
+         */
+        requestPointerLockOnFullScreen: boolean;
+        /**
          * Instantiates a VRExperienceHelper.
          * Helps to quickly add VR support to an existing scene.
          * @param scene The scene the VRExperienceHelper belongs to.
@@ -40751,7 +40766,7 @@ declare module "babylonjs/Gizmos/gizmo" {
         /**
          * The root mesh of the gizmo
          */
-        protected _rootMesh: Mesh;
+        _rootMesh: Mesh;
         private _attachedMesh;
         /**
          * Ratio for the scale of the gizmo (Default: 1)
@@ -42987,6 +43002,33 @@ declare module "babylonjs/Gizmos/gizmoManager" {
         dispose(): void;
     }
 }
+declare module "babylonjs/Gizmos/lightGizmo" {
+    import { Nullable } from "babylonjs/types";
+    import { Gizmo } from "babylonjs/Gizmos/gizmo";
+    import { UtilityLayerRenderer } from "babylonjs/Rendering/utilityLayerRenderer";
+    import { Light } from "babylonjs/Lights/light";
+    /**
+     * Gizmo that enables viewing a light
+     */
+    export class LightGizmo extends Gizmo {
+        private _box;
+        /**
+         * Creates a LightGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _light;
+        /**
+         * The light that the gizmo is attached to
+         */
+        light: Nullable<Light>;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+    }
+}
 declare module "babylonjs/Gizmos/index" {
     export * from "babylonjs/Gizmos/axisDragGizmo";
     export * from "babylonjs/Gizmos/axisScaleGizmo";
@@ -42997,6 +43039,7 @@ declare module "babylonjs/Gizmos/index" {
     export * from "babylonjs/Gizmos/positionGizmo";
     export * from "babylonjs/Gizmos/rotationGizmo";
     export * from "babylonjs/Gizmos/scaleGizmo";
+    export * from "babylonjs/Gizmos/lightGizmo";
 }
 declare module "babylonjs/Shaders/ShadersInclude/backgroundFragmentDeclaration" {
     /** @hidden */
@@ -63951,6 +63994,87 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * A multi-material is used to apply different materials to different parts of the same object without the need of
+     * separate meshes. This can be use to improve performances.
+     * @see http://doc.babylonjs.com/how_to/multi_materials
+     */
+    export class MultiMaterial extends Material {
+        private _subMaterials;
+        /**
+         * Gets or Sets the list of Materials used within the multi material.
+         * They need to be ordered according to the submeshes order in the associated mesh
+         */
+        subMaterials: Nullable<Material>[];
+        /**
+         * Function used to align with Node.getChildren()
+         * @returns the list of Materials used within the multi material
+         */
+        getChildren(): Nullable<Material>[];
+        /**
+         * Instantiates a new Multi Material
+         * A multi-material is used to apply different materials to different parts of the same object without the need of
+         * separate meshes. This can be use to improve performances.
+         * @see http://doc.babylonjs.com/how_to/multi_materials
+         * @param name Define the name in the scene
+         * @param scene Define the scene the material belongs to
+         */
+        constructor(name: string, scene: Scene);
+        private _hookArray;
+        /**
+         * Get one of the submaterial by its index in the submaterials array
+         * @param index The index to look the sub material at
+         * @returns The Material if the index has been defined
+         */
+        getSubMaterial(index: number): Nullable<Material>;
+        /**
+         * Get the list of active textures for the whole sub materials list.
+         * @returns All the textures that will be used during the rendering
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
+         * Gets the current class name of the material e.g. "MultiMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Checks if the material is ready to render the requested sub mesh
+         * @param mesh Define the mesh the submesh belongs to
+         * @param subMesh Define the sub mesh to look readyness for
+         * @param useInstances Define whether or not the material is used with instances
+         * @returns true if ready, otherwise false
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
+        /**
+         * Clones the current material and its related sub materials
+         * @param name Define the name of the newly cloned material
+         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
+         * @returns the cloned material
+         */
+        clone(name: string, cloneChildren?: boolean): MultiMaterial;
+        /**
+         * Serializes the materials into a JSON representation.
+         * @returns the JSON representation
+         */
+        serialize(): any;
+        /**
+         * Dispose the material and release its associated resources
+         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
+         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
+         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
+        /**
+         * Creates a MultiMaterial from parsed MultiMaterial data.
+         * @param parsedMultiMaterial defines parsed MultiMaterial data.
+         * @param scene defines the hosting scene
+         * @returns a new MultiMaterial
+         */
+        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
+    }
+}
+declare module BABYLON {
+    /**
      * Class used to represent data loading progression
      */
     export class SceneLoaderFlags {
@@ -65199,7 +65323,7 @@ declare module BABYLON {
         getAbsolutePosition(): Vector3;
         /**
          * Sets the ShadowLight direction toward the passed target.
-         * @param target The point tot target in local space
+         * @param target The point to target in local space
          * @returns the updated ShadowLight direction
          */
         setDirectionToTarget(target: Vector3): Vector3;
@@ -76609,9 +76733,10 @@ declare module BABYLON {
          * @param allow32BitsIndices when the sum of the vertices > 64k, this must be set to true
          * @param meshSubclass when set, vertices inserted into this Mesh.  Meshes can then be merged into a Mesh sub-class.
          * @param subdivideWithSubMeshes when true (false default), subdivide mesh to his subMesh array with meshes source.
+         * @param multiMultiMaterials when true (false default), subdivide mesh and accept multiple multi materials, ignores subdivideWithSubMeshes.
          * @returns a new mesh
          */
-        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean): Nullable<Mesh>;
+        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean, multiMultiMaterials?: boolean): Nullable<Mesh>;
         /** @hidden */
         addInstance(instance: InstancedMesh): void;
         /** @hidden */
@@ -77180,87 +77305,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * A multi-material is used to apply different materials to different parts of the same object without the need of
-     * separate meshes. This can be use to improve performances.
-     * @see http://doc.babylonjs.com/how_to/multi_materials
-     */
-    export class MultiMaterial extends Material {
-        private _subMaterials;
-        /**
-         * Gets or Sets the list of Materials used within the multi material.
-         * They need to be ordered according to the submeshes order in the associated mesh
-         */
-        subMaterials: Nullable<Material>[];
-        /**
-         * Function used to align with Node.getChildren()
-         * @returns the list of Materials used within the multi material
-         */
-        getChildren(): Nullable<Material>[];
-        /**
-         * Instantiates a new Multi Material
-         * A multi-material is used to apply different materials to different parts of the same object without the need of
-         * separate meshes. This can be use to improve performances.
-         * @see http://doc.babylonjs.com/how_to/multi_materials
-         * @param name Define the name in the scene
-         * @param scene Define the scene the material belongs to
-         */
-        constructor(name: string, scene: Scene);
-        private _hookArray;
-        /**
-         * Get one of the submaterial by its index in the submaterials array
-         * @param index The index to look the sub material at
-         * @returns The Material if the index has been defined
-         */
-        getSubMaterial(index: number): Nullable<Material>;
-        /**
-         * Get the list of active textures for the whole sub materials list.
-         * @returns All the textures that will be used during the rendering
-         */
-        getActiveTextures(): BaseTexture[];
-        /**
-         * Gets the current class name of the material e.g. "MultiMaterial"
-         * Mainly use in serialization.
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Checks if the material is ready to render the requested sub mesh
-         * @param mesh Define the mesh the submesh belongs to
-         * @param subMesh Define the sub mesh to look readyness for
-         * @param useInstances Define whether or not the material is used with instances
-         * @returns true if ready, otherwise false
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
-        /**
-         * Clones the current material and its related sub materials
-         * @param name Define the name of the newly cloned material
-         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
-         * @returns the cloned material
-         */
-        clone(name: string, cloneChildren?: boolean): MultiMaterial;
-        /**
-         * Serializes the materials into a JSON representation.
-         * @returns the JSON representation
-         */
-        serialize(): any;
-        /**
-         * Dispose the material and release its associated resources
-         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
-         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
-         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
-         */
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
-        /**
-         * Creates a MultiMaterial from parsed MultiMaterial data.
-         * @param parsedMultiMaterial defines parsed MultiMaterial data.
-         * @param scene defines the hosting scene
-         * @returns a new MultiMaterial
-         */
-        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class for submeshes
      */
     export class BaseSubMesh {
@@ -83450,6 +83494,15 @@ declare module BABYLON {
          */
         switchFullscreen(requestPointerLock: boolean): void;
         /**
+         * Enters full screen mode
+         * @param requestPointerLock defines if a pointer lock should be requested from the user
+         */
+        enterFullscreen(requestPointerLock: boolean): void;
+        /**
+         * Exits full screen mode
+         */
+        exitFullscreen(): void;
+        /**
          * Clear the current render buffer or the current render target (if any is set up)
          * @param color defines the color to use
          * @param backBuffer defines if the back buffer must be cleared
@@ -95031,6 +95084,11 @@ declare module BABYLON {
         readonly vrDeviceOrientationCamera: Nullable<VRDeviceOrientationFreeCamera>;
         private readonly _teleportationRequestInitiated;
         /**
+         * Defines wether or not Pointer lock should be requested when switching to
+         * full screen.
+         */
+        requestPointerLockOnFullScreen: boolean;
+        /**
          * Instantiates a VRExperienceHelper.
          * Helps to quickly add VR support to an existing scene.
          * @param scene The scene the VRExperienceHelper belongs to.
@@ -95911,7 +95969,7 @@ declare module BABYLON {
         /**
          * The root mesh of the gizmo
          */
-        protected _rootMesh: Mesh;
+        _rootMesh: Mesh;
         private _attachedMesh;
         /**
          * Ratio for the scale of the gizmo (Default: 1)
@@ -97944,6 +98002,29 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /**
+     * Gizmo that enables viewing a light
+     */
+    export class LightGizmo extends Gizmo {
+        private _box;
+        /**
+         * Creates a LightGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _light;
+        /**
+         * The light that the gizmo is attached to
+         */
+        light: Nullable<Light>;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+    }
+}
+declare module BABYLON {
     /** @hidden */
     export var backgroundFragmentDeclaration: {
         name: string;

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

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

+ 2 - 2
dist/preview release/gui/babylon.gui.d.ts

@@ -1085,7 +1085,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
-        _onPointerOut(target: Control): void;
+        _onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
@@ -1579,7 +1579,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
-        _onPointerOut(target: Control): void;
+        _onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */

+ 22 - 7
dist/preview release/gui/babylon.gui.js

@@ -1275,7 +1275,7 @@ var AdvancedDynamicTexture = /** @class */ (function (_super) {
             }
             else if (pi.type === babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["PointerEventTypes"].POINTERMOVE) {
                 if (_this._lastControlOver[pointerId]) {
-                    _this._lastControlOver[pointerId]._onPointerOut(_this._lastControlOver[pointerId]);
+                    _this._lastControlOver[pointerId]._onPointerOut(_this._lastControlOver[pointerId], true);
                 }
                 delete _this._lastControlOver[pointerId];
             }
@@ -1487,11 +1487,12 @@ var Button = /** @class */ (function (_super) {
         return true;
     };
     /** @hidden */
-    Button.prototype._onPointerOut = function (target) {
+    Button.prototype._onPointerOut = function (target, force) {
+        if (force === void 0) { force = false; }
         if (this.pointerOutAnimation) {
             this.pointerOutAnimation();
         }
-        _super.prototype._onPointerOut.call(this, target);
+        _super.prototype._onPointerOut.call(this, target, force);
     };
     /** @hidden */
     Button.prototype._onPointerDown = function (target, coordinates, pointerId, buttonIndex) {
@@ -4772,7 +4773,20 @@ var Control = /** @class */ (function () {
             // get the boudning box of the current measure and last frames measure in global space and invalidate it
             // the previous measure is used to properly clear a control that is scaled down
             _measure__WEBPACK_IMPORTED_MODULE_2__["Measure"].CombineToRef(this._tmpMeasureA, this._prevCurrentMeasureTransformedIntoGlobalSpace, this._tmpMeasureA);
-            this.host.invalidateRect(Math.floor(this._tmpMeasureA.left), Math.floor(this._tmpMeasureA.top), Math.ceil(this._tmpMeasureA.left + this._tmpMeasureA.width), Math.ceil(this._tmpMeasureA.top + this._tmpMeasureA.height));
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                // Expand rect based on shadows
+                var shadowOffsetX = this.shadowOffsetX;
+                var shadowOffsetY = this.shadowOffsetY;
+                var shadowBlur = this.shadowBlur;
+                var leftShadowOffset = Math.min(Math.min(shadowOffsetX, 0) - shadowBlur * 2, 0);
+                var rightShadowOffset = Math.max(Math.max(shadowOffsetX, 0) + shadowBlur * 2, 0);
+                var topShadowOffset = Math.min(Math.min(shadowOffsetY, 0) - shadowBlur * 2, 0);
+                var bottomShadowOffset = Math.max(Math.max(shadowOffsetY, 0) + shadowBlur * 2, 0);
+                this.host.invalidateRect(Math.floor(this._tmpMeasureA.left + leftShadowOffset), Math.floor(this._tmpMeasureA.top + topShadowOffset), Math.ceil(this._tmpMeasureA.left + this._tmpMeasureA.width + rightShadowOffset), Math.ceil(this._tmpMeasureA.top + this._tmpMeasureA.height + bottomShadowOffset));
+            }
+            else {
+                this.host.invalidateRect(Math.floor(this._tmpMeasureA.left), Math.floor(this._tmpMeasureA.top), Math.ceil(this._tmpMeasureA.left + this._tmpMeasureA.width), Math.ceil(this._tmpMeasureA.top + this._tmpMeasureA.height));
+            }
         }
     };
     /** @hidden */
@@ -5169,8 +5183,9 @@ var Control = /** @class */ (function () {
         return true;
     };
     /** @hidden */
-    Control.prototype._onPointerOut = function (target) {
-        if (!this._isEnabled || target === this) {
+    Control.prototype._onPointerOut = function (target, force) {
+        if (force === void 0) { force = false; }
+        if (!force && (!this._isEnabled || target === this)) {
             return;
         }
         this._enterCount = 0;
@@ -5179,7 +5194,7 @@ var Control = /** @class */ (function () {
             canNotify = this.onPointerOutObservable.notifyObservers(this, -1, target, this);
         }
         if (canNotify && this.parent != null) {
-            this.parent._onPointerOut(target);
+            this.parent._onPointerOut(target, force);
         }
     };
     /** @hidden */

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


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


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

@@ -1115,7 +1115,7 @@ declare module "babylonjs-gui/2D/controls/control" {
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
-        _onPointerOut(target: Control): void;
+        _onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
@@ -1628,7 +1628,7 @@ declare module "babylonjs-gui/2D/controls/button" {
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
-        _onPointerOut(target: Control): void;
+        _onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
@@ -4926,7 +4926,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
-        _onPointerOut(target: Control): void;
+        _onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */
@@ -5420,7 +5420,7 @@ declare module BABYLON.GUI {
         /** @hidden */
         _onPointerEnter(target: Control): boolean;
         /** @hidden */
-        _onPointerOut(target: Control): void;
+        _onPointerOut(target: Control, force?: boolean): void;
         /** @hidden */
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number): boolean;
         /** @hidden */

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "4.0.0-alpha.21",
+    "version": "4.0.0-alpha.22",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.21"
+        "babylonjs": "4.0.0-alpha.22"
     },
     "engines": {
         "node": "*"

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


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


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


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

@@ -27,6 +27,8 @@ declare module INSPECTOR {
         };
         blockMutationUpdates: boolean;
         prepareGLTFPlugin(loader: BABYLON.GLTFFileLoader): void;
+        lightGizmos: Array<BABYLON.LightGizmo>;
+        enableLightGizmo(light: BABYLON.Light, enable?: boolean): void;
     }
 }
 declare module INSPECTOR {
@@ -1108,9 +1110,11 @@ declare module INSPECTOR {
     }
     export class LightTreeItemComponent extends React.Component<ILightTreeItemComponentProps, {
         isEnabled: boolean;
+        isGizmoEnabled: boolean;
     }> {
         constructor(props: ILightTreeItemComponentProps);
         switchIsEnabled(): void;
+        toggleGizmo(): void;
         render(): JSX.Element;
     }
 }
@@ -1272,12 +1276,14 @@ declare module INSPECTOR {
         selectedEntity?: any;
         extensibilityGroups?: BABYLON.IExplorerExtensibilityGroup[];
         onSelectionChangedObservable?: BABYLON.Observable<any>;
+        globalState: GlobalState;
     }
     export class SceneTreeItemComponent extends React.Component<ISceneTreeItemComponentProps, {
         isSelected: boolean;
         isInPickingMode: boolean;
         gizmoMode: number;
     }> {
+        private _gizmoLayerOnPointerObserver;
         private _onPointerObserver;
         private _onSelectionChangeObserver;
         private _selectedEntity;

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

@@ -14,6 +14,8 @@ declare module "babylonjs-inspector/components/globalState" {
     import { Observable, Observer } from "babylonjs/Misc/observable";
     import { ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
+    import { Light } from "babylonjs/Lights/light";
+    import { LightGizmo } from "babylonjs/Gizmos/lightGizmo";
     import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
     export class GlobalState {
         onSelectionChangedObservable: Observable<string>;
@@ -34,6 +36,8 @@ declare module "babylonjs-inspector/components/globalState" {
         };
         blockMutationUpdates: boolean;
         prepareGLTFPlugin(loader: GLTFFileLoader): void;
+        lightGizmos: Array<LightGizmo>;
+        enableLightGizmo(light: Light, enable?: boolean): void;
     }
 }
 declare module "babylonjs-inspector/components/actionTabs/paneComponent" {
@@ -1382,9 +1386,11 @@ declare module "babylonjs-inspector/components/sceneExplorer/entities/lightTreeI
     }
     export class LightTreeItemComponent extends React.Component<ILightTreeItemComponentProps, {
         isEnabled: boolean;
+        isGizmoEnabled: boolean;
     }> {
         constructor(props: ILightTreeItemComponentProps);
         switchIsEnabled(): void;
+        toggleGizmo(): void;
         render(): JSX.Element;
     }
 }
@@ -1574,18 +1580,21 @@ declare module "babylonjs-inspector/components/sceneExplorer/entities/sceneTreeI
     import { IExplorerExtensibilityGroup } from "babylonjs/Debug/debugLayer";
     import { Scene } from "babylonjs/scene";
     import * as React from "react";
+    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface ISceneTreeItemComponentProps {
         scene: Scene;
         onRefresh: () => void;
         selectedEntity?: any;
         extensibilityGroups?: IExplorerExtensibilityGroup[];
         onSelectionChangedObservable?: Observable<any>;
+        globalState: GlobalState;
     }
     export class SceneTreeItemComponent extends React.Component<ISceneTreeItemComponentProps, {
         isSelected: boolean;
         isInPickingMode: boolean;
         gizmoMode: number;
     }> {
+        private _gizmoLayerOnPointerObserver;
         private _onPointerObserver;
         private _onSelectionChangeObserver;
         private _selectedEntity;
@@ -1777,6 +1786,8 @@ declare module INSPECTOR {
         };
         blockMutationUpdates: boolean;
         prepareGLTFPlugin(loader: BABYLON.GLTFFileLoader): void;
+        lightGizmos: Array<BABYLON.LightGizmo>;
+        enableLightGizmo(light: BABYLON.Light, enable?: boolean): void;
     }
 }
 declare module INSPECTOR {
@@ -2858,9 +2869,11 @@ declare module INSPECTOR {
     }
     export class LightTreeItemComponent extends React.Component<ILightTreeItemComponentProps, {
         isEnabled: boolean;
+        isGizmoEnabled: boolean;
     }> {
         constructor(props: ILightTreeItemComponentProps);
         switchIsEnabled(): void;
+        toggleGizmo(): void;
         render(): JSX.Element;
     }
 }
@@ -3022,12 +3035,14 @@ declare module INSPECTOR {
         selectedEntity?: any;
         extensibilityGroups?: BABYLON.IExplorerExtensibilityGroup[];
         onSelectionChangedObservable?: BABYLON.Observable<any>;
+        globalState: GlobalState;
     }
     export class SceneTreeItemComponent extends React.Component<ISceneTreeItemComponentProps, {
         isSelected: boolean;
         isInPickingMode: boolean;
         gizmoMode: number;
     }> {
+        private _gizmoLayerOnPointerObserver;
         private _onPointerObserver;
         private _onSelectionChangeObserver;
         private _selectedEntity;

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

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

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "4.0.0-alpha.21",
+    "version": "4.0.0-alpha.22",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "4.0.0-alpha.21",
-        "babylonjs": "4.0.0-alpha.21"
+        "babylonjs-gltf2interface": "4.0.0-alpha.22",
+        "babylonjs": "4.0.0-alpha.22"
     },
     "engines": {
         "node": "*"

+ 22 - 7
dist/preview release/materialsLibrary/babylon.terrainMaterial.js

@@ -553,17 +553,32 @@ var TerrainMaterial = /** @class */ (function (_super) {
         var engine = scene.getEngine();
         // Textures
         if (scene.texturesEnabled) {
-            if (this.mixTexture && babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].DiffuseTextureEnabled) {
-                if (!this.mixTexture.isReady()) {
+            if (!this.mixTexture || !this.mixTexture.isReady()) {
+                return false;
+            }
+            defines._needUVs = true;
+            if (babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].DiffuseTextureEnabled) {
+                if (!this.diffuseTexture1 || !this.diffuseTexture1.isReady()) {
                     return false;
                 }
-                else {
-                    defines._needUVs = true;
-                    defines.DIFFUSE = true;
+                if (!this.diffuseTexture2 || !this.diffuseTexture2.isReady()) {
+                    return false;
                 }
+                if (!this.diffuseTexture3 || !this.diffuseTexture3.isReady()) {
+                    return false;
+                }
+                defines.DIFFUSE = true;
             }
-            if ((this.bumpTexture1 || this.bumpTexture2 || this.bumpTexture3) && babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].BumpTextureEnabled) {
-                defines._needUVs = true;
+            if (this.bumpTexture1 && this.bumpTexture2 && this.bumpTexture3 && babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].BumpTextureEnabled) {
+                if (!this.bumpTexture1.isReady()) {
+                    return false;
+                }
+                if (!this.bumpTexture2.isReady()) {
+                    return false;
+                }
+                if (!this.bumpTexture3.isReady()) {
+                    return false;
+                }
                 defines._needNormals = true;
                 defines.BUMP = true;
             }

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


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


+ 22 - 7
dist/preview release/materialsLibrary/babylonjs.materials.js

@@ -5510,17 +5510,32 @@ var TerrainMaterial = /** @class */ (function (_super) {
         var engine = scene.getEngine();
         // Textures
         if (scene.texturesEnabled) {
-            if (this.mixTexture && babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].DiffuseTextureEnabled) {
-                if (!this.mixTexture.isReady()) {
+            if (!this.mixTexture || !this.mixTexture.isReady()) {
+                return false;
+            }
+            defines._needUVs = true;
+            if (babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].DiffuseTextureEnabled) {
+                if (!this.diffuseTexture1 || !this.diffuseTexture1.isReady()) {
                     return false;
                 }
-                else {
-                    defines._needUVs = true;
-                    defines.DIFFUSE = true;
+                if (!this.diffuseTexture2 || !this.diffuseTexture2.isReady()) {
+                    return false;
+                }
+                if (!this.diffuseTexture3 || !this.diffuseTexture3.isReady()) {
+                    return false;
                 }
+                defines.DIFFUSE = true;
             }
-            if ((this.bumpTexture1 || this.bumpTexture2 || this.bumpTexture3) && babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].BumpTextureEnabled) {
-                defines._needUVs = true;
+            if (this.bumpTexture1 && this.bumpTexture2 && this.bumpTexture3 && babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__["MaterialFlags"].BumpTextureEnabled) {
+                if (!this.bumpTexture1.isReady()) {
+                    return false;
+                }
+                if (!this.bumpTexture2.isReady()) {
+                    return false;
+                }
+                if (!this.bumpTexture3.isReady()) {
+                    return false;
+                }
                 defines._needNormals = true;
                 defines.BUMP = true;
             }

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


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


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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.21",
+    "version": "4.0.0-alpha.22",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.21"
+        "babylonjs": "4.0.0-alpha.22"
     },
     "engines": {
         "node": "*"

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

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

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

@@ -1 +1 @@
-{"engineOnly":303853,"sceneOnly":503858,"minGridMaterial":619343,"minStandardMaterial":740051}
+{"engineOnly":304017,"sceneOnly":504022,"minGridMaterial":622541,"minStandardMaterial":743249}

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.21",
+    "version": "4.0.0-alpha.22",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.21"
+        "babylonjs": "4.0.0-alpha.22"
     },
     "engines": {
         "node": "*"

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.0.0-alpha.21",
+    "version": "4.0.0-alpha.22",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.21"
+        "babylonjs": "4.0.0-alpha.22"
     },
     "engines": {
         "node": "*"

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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "4.0.0-alpha.21",
+    "version": "4.0.0-alpha.22",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.0.0-alpha.21",
-        "babylonjs-gltf2interface": "4.0.0-alpha.21"
+        "babylonjs": "4.0.0-alpha.22",
+        "babylonjs-gltf2interface": "4.0.0-alpha.22"
     },
     "engines": {
         "node": "*"

+ 255 - 174
dist/preview release/viewer/babylon.module.d.ts

@@ -7489,6 +7489,93 @@ declare module "babylonjs/Misc/smartArray" {
         concatWithNoDuplicate(array: any): void;
     }
 }
+declare module "babylonjs/Materials/multiMaterial" {
+    import { Nullable } from "babylonjs/types";
+    import { Scene } from "babylonjs/scene";
+    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
+    import { BaseSubMesh } from "babylonjs/Meshes/subMesh";
+    import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
+    import { Material } from "babylonjs/Materials/material";
+    /**
+     * A multi-material is used to apply different materials to different parts of the same object without the need of
+     * separate meshes. This can be use to improve performances.
+     * @see http://doc.babylonjs.com/how_to/multi_materials
+     */
+    export class MultiMaterial extends Material {
+        private _subMaterials;
+        /**
+         * Gets or Sets the list of Materials used within the multi material.
+         * They need to be ordered according to the submeshes order in the associated mesh
+         */
+        subMaterials: Nullable<Material>[];
+        /**
+         * Function used to align with Node.getChildren()
+         * @returns the list of Materials used within the multi material
+         */
+        getChildren(): Nullable<Material>[];
+        /**
+         * Instantiates a new Multi Material
+         * A multi-material is used to apply different materials to different parts of the same object without the need of
+         * separate meshes. This can be use to improve performances.
+         * @see http://doc.babylonjs.com/how_to/multi_materials
+         * @param name Define the name in the scene
+         * @param scene Define the scene the material belongs to
+         */
+        constructor(name: string, scene: Scene);
+        private _hookArray;
+        /**
+         * Get one of the submaterial by its index in the submaterials array
+         * @param index The index to look the sub material at
+         * @returns The Material if the index has been defined
+         */
+        getSubMaterial(index: number): Nullable<Material>;
+        /**
+         * Get the list of active textures for the whole sub materials list.
+         * @returns All the textures that will be used during the rendering
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
+         * Gets the current class name of the material e.g. "MultiMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Checks if the material is ready to render the requested sub mesh
+         * @param mesh Define the mesh the submesh belongs to
+         * @param subMesh Define the sub mesh to look readyness for
+         * @param useInstances Define whether or not the material is used with instances
+         * @returns true if ready, otherwise false
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
+        /**
+         * Clones the current material and its related sub materials
+         * @param name Define the name of the newly cloned material
+         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
+         * @returns the cloned material
+         */
+        clone(name: string, cloneChildren?: boolean): MultiMaterial;
+        /**
+         * Serializes the materials into a JSON representation.
+         * @returns the JSON representation
+         */
+        serialize(): any;
+        /**
+         * Dispose the material and release its associated resources
+         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
+         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
+         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
+        /**
+         * Creates a MultiMaterial from parsed MultiMaterial data.
+         * @param parsedMultiMaterial defines parsed MultiMaterial data.
+         * @param scene defines the hosting scene
+         * @returns a new MultiMaterial
+         */
+        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
+    }
+}
 declare module "babylonjs/Loading/sceneLoaderFlags" {
     /**
      * Class used to represent data loading progression
@@ -8779,7 +8866,7 @@ declare module "babylonjs/Lights/shadowLight" {
         getAbsolutePosition(): Vector3;
         /**
          * Sets the ShadowLight direction toward the passed target.
-         * @param target The point tot target in local space
+         * @param target The point to target in local space
          * @returns the updated ShadowLight direction
          */
         setDirectionToTarget(target: Vector3): Vector3;
@@ -20603,9 +20690,10 @@ declare module "babylonjs/Meshes/mesh" {
          * @param allow32BitsIndices when the sum of the vertices > 64k, this must be set to true
          * @param meshSubclass when set, vertices inserted into this Mesh.  Meshes can then be merged into a Mesh sub-class.
          * @param subdivideWithSubMeshes when true (false default), subdivide mesh to his subMesh array with meshes source.
+         * @param multiMultiMaterials when true (false default), subdivide mesh and accept multiple multi materials, ignores subdivideWithSubMeshes.
          * @returns a new mesh
          */
-        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean): Nullable<Mesh>;
+        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean, multiMultiMaterials?: boolean): Nullable<Mesh>;
         /** @hidden */
         addInstance(instance: InstancedMesh): void;
         /** @hidden */
@@ -21187,93 +21275,6 @@ declare module "babylonjs/Materials/material" {
         static Parse(parsedMaterial: any, scene: Scene, rootUrl: string): any;
     }
 }
-declare module "babylonjs/Materials/multiMaterial" {
-    import { Nullable } from "babylonjs/types";
-    import { Scene } from "babylonjs/scene";
-    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { BaseSubMesh } from "babylonjs/Meshes/subMesh";
-    import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
-    import { Material } from "babylonjs/Materials/material";
-    /**
-     * A multi-material is used to apply different materials to different parts of the same object without the need of
-     * separate meshes. This can be use to improve performances.
-     * @see http://doc.babylonjs.com/how_to/multi_materials
-     */
-    export class MultiMaterial extends Material {
-        private _subMaterials;
-        /**
-         * Gets or Sets the list of Materials used within the multi material.
-         * They need to be ordered according to the submeshes order in the associated mesh
-         */
-        subMaterials: Nullable<Material>[];
-        /**
-         * Function used to align with Node.getChildren()
-         * @returns the list of Materials used within the multi material
-         */
-        getChildren(): Nullable<Material>[];
-        /**
-         * Instantiates a new Multi Material
-         * A multi-material is used to apply different materials to different parts of the same object without the need of
-         * separate meshes. This can be use to improve performances.
-         * @see http://doc.babylonjs.com/how_to/multi_materials
-         * @param name Define the name in the scene
-         * @param scene Define the scene the material belongs to
-         */
-        constructor(name: string, scene: Scene);
-        private _hookArray;
-        /**
-         * Get one of the submaterial by its index in the submaterials array
-         * @param index The index to look the sub material at
-         * @returns The Material if the index has been defined
-         */
-        getSubMaterial(index: number): Nullable<Material>;
-        /**
-         * Get the list of active textures for the whole sub materials list.
-         * @returns All the textures that will be used during the rendering
-         */
-        getActiveTextures(): BaseTexture[];
-        /**
-         * Gets the current class name of the material e.g. "MultiMaterial"
-         * Mainly use in serialization.
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Checks if the material is ready to render the requested sub mesh
-         * @param mesh Define the mesh the submesh belongs to
-         * @param subMesh Define the sub mesh to look readyness for
-         * @param useInstances Define whether or not the material is used with instances
-         * @returns true if ready, otherwise false
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
-        /**
-         * Clones the current material and its related sub materials
-         * @param name Define the name of the newly cloned material
-         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
-         * @returns the cloned material
-         */
-        clone(name: string, cloneChildren?: boolean): MultiMaterial;
-        /**
-         * Serializes the materials into a JSON representation.
-         * @returns the JSON representation
-         */
-        serialize(): any;
-        /**
-         * Dispose the material and release its associated resources
-         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
-         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
-         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
-         */
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
-        /**
-         * Creates a MultiMaterial from parsed MultiMaterial data.
-         * @param parsedMultiMaterial defines parsed MultiMaterial data.
-         * @param scene defines the hosting scene
-         * @returns a new MultiMaterial
-         */
-        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
-    }
-}
 declare module "babylonjs/Meshes/subMesh" {
     import { Nullable, IndicesArray, DeepImmutable } from "babylonjs/types";
     import { Matrix, Vector3, Plane } from "babylonjs/Maths/math";
@@ -27625,6 +27626,15 @@ declare module "babylonjs/Engines/engine" {
          */
         switchFullscreen(requestPointerLock: boolean): void;
         /**
+         * Enters full screen mode
+         * @param requestPointerLock defines if a pointer lock should be requested from the user
+         */
+        enterFullscreen(requestPointerLock: boolean): void;
+        /**
+         * Exits full screen mode
+         */
+        exitFullscreen(): void;
+        /**
          * Clear the current render buffer or the current render target (if any is set up)
          * @param color defines the color to use
          * @param backBuffer defines if the back buffer must be cleared
@@ -39749,6 +39759,11 @@ declare module "babylonjs/Cameras/VR/vrExperienceHelper" {
         readonly vrDeviceOrientationCamera: Nullable<VRDeviceOrientationFreeCamera>;
         private readonly _teleportationRequestInitiated;
         /**
+         * Defines wether or not Pointer lock should be requested when switching to
+         * full screen.
+         */
+        requestPointerLockOnFullScreen: boolean;
+        /**
          * Instantiates a VRExperienceHelper.
          * Helps to quickly add VR support to an existing scene.
          * @param scene The scene the VRExperienceHelper belongs to.
@@ -40751,7 +40766,7 @@ declare module "babylonjs/Gizmos/gizmo" {
         /**
          * The root mesh of the gizmo
          */
-        protected _rootMesh: Mesh;
+        _rootMesh: Mesh;
         private _attachedMesh;
         /**
          * Ratio for the scale of the gizmo (Default: 1)
@@ -42987,6 +43002,33 @@ declare module "babylonjs/Gizmos/gizmoManager" {
         dispose(): void;
     }
 }
+declare module "babylonjs/Gizmos/lightGizmo" {
+    import { Nullable } from "babylonjs/types";
+    import { Gizmo } from "babylonjs/Gizmos/gizmo";
+    import { UtilityLayerRenderer } from "babylonjs/Rendering/utilityLayerRenderer";
+    import { Light } from "babylonjs/Lights/light";
+    /**
+     * Gizmo that enables viewing a light
+     */
+    export class LightGizmo extends Gizmo {
+        private _box;
+        /**
+         * Creates a LightGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _light;
+        /**
+         * The light that the gizmo is attached to
+         */
+        light: Nullable<Light>;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+    }
+}
 declare module "babylonjs/Gizmos/index" {
     export * from "babylonjs/Gizmos/axisDragGizmo";
     export * from "babylonjs/Gizmos/axisScaleGizmo";
@@ -42997,6 +43039,7 @@ declare module "babylonjs/Gizmos/index" {
     export * from "babylonjs/Gizmos/positionGizmo";
     export * from "babylonjs/Gizmos/rotationGizmo";
     export * from "babylonjs/Gizmos/scaleGizmo";
+    export * from "babylonjs/Gizmos/lightGizmo";
 }
 declare module "babylonjs/Shaders/ShadersInclude/backgroundFragmentDeclaration" {
     /** @hidden */
@@ -63951,6 +63994,87 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * A multi-material is used to apply different materials to different parts of the same object without the need of
+     * separate meshes. This can be use to improve performances.
+     * @see http://doc.babylonjs.com/how_to/multi_materials
+     */
+    export class MultiMaterial extends Material {
+        private _subMaterials;
+        /**
+         * Gets or Sets the list of Materials used within the multi material.
+         * They need to be ordered according to the submeshes order in the associated mesh
+         */
+        subMaterials: Nullable<Material>[];
+        /**
+         * Function used to align with Node.getChildren()
+         * @returns the list of Materials used within the multi material
+         */
+        getChildren(): Nullable<Material>[];
+        /**
+         * Instantiates a new Multi Material
+         * A multi-material is used to apply different materials to different parts of the same object without the need of
+         * separate meshes. This can be use to improve performances.
+         * @see http://doc.babylonjs.com/how_to/multi_materials
+         * @param name Define the name in the scene
+         * @param scene Define the scene the material belongs to
+         */
+        constructor(name: string, scene: Scene);
+        private _hookArray;
+        /**
+         * Get one of the submaterial by its index in the submaterials array
+         * @param index The index to look the sub material at
+         * @returns The Material if the index has been defined
+         */
+        getSubMaterial(index: number): Nullable<Material>;
+        /**
+         * Get the list of active textures for the whole sub materials list.
+         * @returns All the textures that will be used during the rendering
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
+         * Gets the current class name of the material e.g. "MultiMaterial"
+         * Mainly use in serialization.
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Checks if the material is ready to render the requested sub mesh
+         * @param mesh Define the mesh the submesh belongs to
+         * @param subMesh Define the sub mesh to look readyness for
+         * @param useInstances Define whether or not the material is used with instances
+         * @returns true if ready, otherwise false
+         */
+        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
+        /**
+         * Clones the current material and its related sub materials
+         * @param name Define the name of the newly cloned material
+         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
+         * @returns the cloned material
+         */
+        clone(name: string, cloneChildren?: boolean): MultiMaterial;
+        /**
+         * Serializes the materials into a JSON representation.
+         * @returns the JSON representation
+         */
+        serialize(): any;
+        /**
+         * Dispose the material and release its associated resources
+         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
+         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
+         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
+         */
+        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
+        /**
+         * Creates a MultiMaterial from parsed MultiMaterial data.
+         * @param parsedMultiMaterial defines parsed MultiMaterial data.
+         * @param scene defines the hosting scene
+         * @returns a new MultiMaterial
+         */
+        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
+    }
+}
+declare module BABYLON {
+    /**
      * Class used to represent data loading progression
      */
     export class SceneLoaderFlags {
@@ -65199,7 +65323,7 @@ declare module BABYLON {
         getAbsolutePosition(): Vector3;
         /**
          * Sets the ShadowLight direction toward the passed target.
-         * @param target The point tot target in local space
+         * @param target The point to target in local space
          * @returns the updated ShadowLight direction
          */
         setDirectionToTarget(target: Vector3): Vector3;
@@ -76609,9 +76733,10 @@ declare module BABYLON {
          * @param allow32BitsIndices when the sum of the vertices > 64k, this must be set to true
          * @param meshSubclass when set, vertices inserted into this Mesh.  Meshes can then be merged into a Mesh sub-class.
          * @param subdivideWithSubMeshes when true (false default), subdivide mesh to his subMesh array with meshes source.
+         * @param multiMultiMaterials when true (false default), subdivide mesh and accept multiple multi materials, ignores subdivideWithSubMeshes.
          * @returns a new mesh
          */
-        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean): Nullable<Mesh>;
+        static MergeMeshes(meshes: Array<Mesh>, disposeSource?: boolean, allow32BitsIndices?: boolean, meshSubclass?: Mesh, subdivideWithSubMeshes?: boolean, multiMultiMaterials?: boolean): Nullable<Mesh>;
         /** @hidden */
         addInstance(instance: InstancedMesh): void;
         /** @hidden */
@@ -77180,87 +77305,6 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * A multi-material is used to apply different materials to different parts of the same object without the need of
-     * separate meshes. This can be use to improve performances.
-     * @see http://doc.babylonjs.com/how_to/multi_materials
-     */
-    export class MultiMaterial extends Material {
-        private _subMaterials;
-        /**
-         * Gets or Sets the list of Materials used within the multi material.
-         * They need to be ordered according to the submeshes order in the associated mesh
-         */
-        subMaterials: Nullable<Material>[];
-        /**
-         * Function used to align with Node.getChildren()
-         * @returns the list of Materials used within the multi material
-         */
-        getChildren(): Nullable<Material>[];
-        /**
-         * Instantiates a new Multi Material
-         * A multi-material is used to apply different materials to different parts of the same object without the need of
-         * separate meshes. This can be use to improve performances.
-         * @see http://doc.babylonjs.com/how_to/multi_materials
-         * @param name Define the name in the scene
-         * @param scene Define the scene the material belongs to
-         */
-        constructor(name: string, scene: Scene);
-        private _hookArray;
-        /**
-         * Get one of the submaterial by its index in the submaterials array
-         * @param index The index to look the sub material at
-         * @returns The Material if the index has been defined
-         */
-        getSubMaterial(index: number): Nullable<Material>;
-        /**
-         * Get the list of active textures for the whole sub materials list.
-         * @returns All the textures that will be used during the rendering
-         */
-        getActiveTextures(): BaseTexture[];
-        /**
-         * Gets the current class name of the material e.g. "MultiMaterial"
-         * Mainly use in serialization.
-         * @returns the class name
-         */
-        getClassName(): string;
-        /**
-         * Checks if the material is ready to render the requested sub mesh
-         * @param mesh Define the mesh the submesh belongs to
-         * @param subMesh Define the sub mesh to look readyness for
-         * @param useInstances Define whether or not the material is used with instances
-         * @returns true if ready, otherwise false
-         */
-        isReadyForSubMesh(mesh: AbstractMesh, subMesh: BaseSubMesh, useInstances?: boolean): boolean;
-        /**
-         * Clones the current material and its related sub materials
-         * @param name Define the name of the newly cloned material
-         * @param cloneChildren Define if submaterial will be cloned or shared with the parent instance
-         * @returns the cloned material
-         */
-        clone(name: string, cloneChildren?: boolean): MultiMaterial;
-        /**
-         * Serializes the materials into a JSON representation.
-         * @returns the JSON representation
-         */
-        serialize(): any;
-        /**
-         * Dispose the material and release its associated resources
-         * @param forceDisposeEffect Define if we want to force disposing the associated effect (if false the shader is not released and could be reuse later on)
-         * @param forceDisposeTextures Define if we want to force disposing the associated textures (if false, they will not be disposed and can still be use elsewhere in the app)
-         * @param forceDisposeChildren Define if we want to force disposing the associated submaterials (if false, they will not be disposed and can still be use elsewhere in the app)
-         */
-        dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean, forceDisposeChildren?: boolean): void;
-        /**
-         * Creates a MultiMaterial from parsed MultiMaterial data.
-         * @param parsedMultiMaterial defines parsed MultiMaterial data.
-         * @param scene defines the hosting scene
-         * @returns a new MultiMaterial
-         */
-        static ParseMultiMaterial(parsedMultiMaterial: any, scene: Scene): MultiMaterial;
-    }
-}
-declare module BABYLON {
-    /**
      * Base class for submeshes
      */
     export class BaseSubMesh {
@@ -83450,6 +83494,15 @@ declare module BABYLON {
          */
         switchFullscreen(requestPointerLock: boolean): void;
         /**
+         * Enters full screen mode
+         * @param requestPointerLock defines if a pointer lock should be requested from the user
+         */
+        enterFullscreen(requestPointerLock: boolean): void;
+        /**
+         * Exits full screen mode
+         */
+        exitFullscreen(): void;
+        /**
          * Clear the current render buffer or the current render target (if any is set up)
          * @param color defines the color to use
          * @param backBuffer defines if the back buffer must be cleared
@@ -95031,6 +95084,11 @@ declare module BABYLON {
         readonly vrDeviceOrientationCamera: Nullable<VRDeviceOrientationFreeCamera>;
         private readonly _teleportationRequestInitiated;
         /**
+         * Defines wether or not Pointer lock should be requested when switching to
+         * full screen.
+         */
+        requestPointerLockOnFullScreen: boolean;
+        /**
          * Instantiates a VRExperienceHelper.
          * Helps to quickly add VR support to an existing scene.
          * @param scene The scene the VRExperienceHelper belongs to.
@@ -95911,7 +95969,7 @@ declare module BABYLON {
         /**
          * The root mesh of the gizmo
          */
-        protected _rootMesh: Mesh;
+        _rootMesh: Mesh;
         private _attachedMesh;
         /**
          * Ratio for the scale of the gizmo (Default: 1)
@@ -97944,6 +98002,29 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /**
+     * Gizmo that enables viewing a light
+     */
+    export class LightGizmo extends Gizmo {
+        private _box;
+        /**
+         * Creates a LightGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _light;
+        /**
+         * The light that the gizmo is attached to
+         */
+        light: Nullable<Light>;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+    }
+}
+declare module BABYLON {
     /** @hidden */
     export var backgroundFragmentDeclaration: {
         name: string;

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


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


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

@@ -23,7 +23,7 @@
   - Added new [ScrollViewer](https://doc.babylonjs.com/how_to/scrollviewer) with mouse wheel scrolling for larger containers to be viewed using Sliders ([JohnK](https://github.com/BabylonJSGuide/) / [Deltakosh](https://github.com/deltakosh))
   - Moved to a measure / draw mechanism ([Deltakosh](https://github.com/deltakosh))
   - Added support for [nine patch stretch](https://www.babylonjs-playground.com/#G5H9IN#2) mode for images. ([Deltakosh](https://github.com/deltakosh))
-  - InvalidateRect added to AdvancedDynamicTexture to improve perf for heavily populated GUIs ([TrevorDev](https://github.com/TrevorDev))
+  - InvalidateRect added to AdvancedDynamicTexture to improve perf for heavily populated GUIs, works with shadows ([TrevorDev](https://github.com/TrevorDev))
 
 ## Updates
 
@@ -97,6 +97,7 @@
 - Added transparency support to `GlowLayer` ([Sebavan](https://github.com/Sebavan))
 - Added option `forceDisposeChildren` to multiMaterial.dispose ([danjpar](https://github.com/danjpar))
 - Added Pointer bindings for FollowCamera. ([mrdunk](https://github.com))
+- Inspector light gizmo ([TrevorDev](https://github.com/TrevorDev))
 - Added option `multiMultiMaterials` to mesh.mergeMeshes ([danjpar](https://github.com/danjpar))
 - Expose fallback camera distortion metrics option in vrExperienceHelper ([TrevorDev](https://github.com/TrevorDev))
 
@@ -121,6 +122,7 @@
 - Added the `cameraOffset` vector property in the `SkyMaterial` to get an offset according to the horizon ([julien-moreau](https://github.com/julien-moreau))
 - Fixed `GradientMaterial` to consider disableLighting working as emissive ([julien-moreau](https://github.com/julien-moreau))
 - Fixed fresnel term computation in `WaterMaterial` ([julien-moreau](https://github.com/julien-moreau))
+- Fixed `TerrainMaterial.isReadyForSubMesh` to remove WebGL warnings ([julien-moreau](https://github.com/julien-moreau))
 
 ## Bug fixes
 - Fixed TransformNode.setDirection (orientation was wrong) ([Deltakosh](https://github.com/deltakosh))

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

@@ -760,7 +760,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
                 }
             } else if (pi.type === PointerEventTypes.POINTERMOVE) {
                 if (this._lastControlOver[pointerId]) {
-                    this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId]);
+                    this._lastControlOver[pointerId]._onPointerOut(this._lastControlOver[pointerId], true);
                 }
                 delete this._lastControlOver[pointerId];
             }

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

@@ -111,12 +111,12 @@ export class Button extends Rectangle {
     }
 
     /** @hidden */
-    public _onPointerOut(target: Control): void {
+    public _onPointerOut(target: Control, force = false): void {
         if (this.pointerOutAnimation) {
             this.pointerOutAnimation();
         }
 
-        super._onPointerOut(target);
+        super._onPointerOut(target, force);
     }
 
     /** @hidden */

+ 31 - 9
gui/src/2D/controls/control.ts

@@ -1118,12 +1118,32 @@ export class Control {
             // the previous measure is used to properly clear a control that is scaled down
             Measure.CombineToRef(this._tmpMeasureA, this._prevCurrentMeasureTransformedIntoGlobalSpace, this._tmpMeasureA);
 
-            this.host.invalidateRect(
-                Math.floor(this._tmpMeasureA.left),
-                Math.floor(this._tmpMeasureA.top),
-                Math.ceil(this._tmpMeasureA.left + this._tmpMeasureA.width),
-                Math.ceil(this._tmpMeasureA.top + this._tmpMeasureA.height),
-            );
+            if (this.shadowBlur || this.shadowOffsetX || this.shadowOffsetY) {
+                // Expand rect based on shadows
+                var shadowOffsetX = this.shadowOffsetX;
+                var shadowOffsetY = this.shadowOffsetY;
+                var shadowBlur = this.shadowBlur;
+
+                var leftShadowOffset = Math.min(Math.min(shadowOffsetX, 0) - shadowBlur * 2, 0);
+                var rightShadowOffset = Math.max(Math.max(shadowOffsetX, 0) + shadowBlur * 2, 0);
+                var topShadowOffset = Math.min(Math.min(shadowOffsetY, 0) - shadowBlur * 2, 0);
+                var bottomShadowOffset = Math.max(Math.max(shadowOffsetY, 0) + shadowBlur * 2, 0);
+
+                this.host.invalidateRect(
+                    Math.floor(this._tmpMeasureA.left + leftShadowOffset),
+                    Math.floor(this._tmpMeasureA.top + topShadowOffset),
+                    Math.ceil(this._tmpMeasureA.left + this._tmpMeasureA.width + rightShadowOffset),
+                    Math.ceil(this._tmpMeasureA.top + this._tmpMeasureA.height + bottomShadowOffset),
+                );
+            } else {
+                this.host.invalidateRect(
+                    Math.floor(this._tmpMeasureA.left),
+                    Math.floor(this._tmpMeasureA.top),
+                    Math.ceil(this._tmpMeasureA.left + this._tmpMeasureA.width),
+                    Math.ceil(this._tmpMeasureA.top + this._tmpMeasureA.height),
+                );
+            }
+
         }
     }
 
@@ -1609,8 +1629,8 @@ export class Control {
     }
 
     /** @hidden */
-    public _onPointerOut(target: Control): void {
-        if (!this._isEnabled || target === this) {
+    public _onPointerOut(target: Control, force = false): void {
+        if (!force && (!this._isEnabled || target === this)) {
             return;
         }
         this._enterCount = 0;
@@ -1621,7 +1641,9 @@ export class Control {
             canNotify = this.onPointerOutObservable.notifyObservers(this, -1, target, this);
         }
 
-        if (canNotify && this.parent != null) { this.parent._onPointerOut(target); }
+        if (canNotify && this.parent != null) {
+            this.parent._onPointerOut(target, force);
+        }
     }
 
     /** @hidden */

+ 21 - 1
inspector/src/components/globalState.ts

@@ -5,7 +5,8 @@ import { Nullable } from "babylonjs/types";
 import { Observable, Observer } from "babylonjs/Misc/observable";
 import { ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs/Loading/sceneLoader";
 import { Scene } from "babylonjs/scene";
-
+import { Light } from "babylonjs/Lights/light";
+import { LightGizmo } from "babylonjs/Gizmos/lightGizmo";
 import { PropertyChangedEvent } from "./propertyChangedEvent";
 
 export class GlobalState {
@@ -51,4 +52,23 @@ export class GlobalState {
             }
         });
     }
+
+    // Light gizmos
+    public lightGizmos: Array<LightGizmo> = [];
+    public enableLightGizmo(light: Light, enable = true) {
+        if (enable) {
+            if (!light.reservedDataStore) {
+                light.reservedDataStore = {}
+            }
+            if (!light.reservedDataStore.lightGizmo) {
+                light.reservedDataStore.lightGizmo = new LightGizmo();
+                this.lightGizmos.push(light.reservedDataStore.lightGizmo)
+                light.reservedDataStore.lightGizmo.light = light;
+            }
+        } else if (light.reservedDataStore && light.reservedDataStore.lightGizmo) {
+            this.lightGizmos.splice(this.lightGizmos.indexOf(light.reservedDataStore.lightGizmo), 1);
+            light.reservedDataStore.lightGizmo.dispose();
+            light.reservedDataStore.lightGizmo = null;
+        }
+    }
 }

+ 19 - 4
inspector/src/components/sceneExplorer/entities/lightTreeItemComponent.tsx

@@ -2,7 +2,7 @@ import { IExplorerExtensibilityGroup } from "babylonjs/Debug/debugLayer";
 import { Light } from "babylonjs/Lights/light";
 
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faLightbulb } from '@fortawesome/free-solid-svg-icons';
+import { faLightbulb, faEye } from '@fortawesome/free-solid-svg-icons';
 import { faLightbulb as faLightbubRegular } from '@fortawesome/free-regular-svg-icons';
 import { TreeItemLabelComponent } from "../treeItemLabelComponent";
 import { ExtensionsComponent } from "../extensionsComponent";
@@ -16,13 +16,13 @@ interface ILightTreeItemComponentProps {
     globalState: GlobalState
 }
 
-export class LightTreeItemComponent extends React.Component<ILightTreeItemComponentProps, { isEnabled: boolean }> {
+export class LightTreeItemComponent extends React.Component<ILightTreeItemComponentProps, { isEnabled: boolean, isGizmoEnabled:boolean }> {
     constructor(props: ILightTreeItemComponentProps) {
         super(props);
 
         const light = this.props.light;
 
-        this.state = { isEnabled: light.isEnabled() };
+        this.state = { isEnabled: light.isEnabled(), isGizmoEnabled: (light.reservedDataStore && light.reservedDataStore.lightGizmo) };
     }
 
     switchIsEnabled(): void {
@@ -33,15 +33,30 @@ export class LightTreeItemComponent extends React.Component<ILightTreeItemCompon
         this.setState({ isEnabled: light.isEnabled() });
     }
 
+    toggleGizmo(): void {
+        const light = this.props.light;
+        if(light.reservedDataStore && light.reservedDataStore.lightGizmo){
+            this.props.globalState.enableLightGizmo(light, false);
+            this.setState({ isGizmoEnabled: false });
+        }else{
+            this.props.globalState.enableLightGizmo(light, true);
+            this.setState({ isGizmoEnabled: true });
+        }
+    }
+
     render() {
         const isEnabledElement = this.state.isEnabled ? <FontAwesomeIcon icon={faLightbubRegular} /> : <FontAwesomeIcon icon={faLightbubRegular} className="isNotActive" />;
+        const isGizmoEnabled = this.state.isGizmoEnabled ? <FontAwesomeIcon icon={faEye} /> : <FontAwesomeIcon icon={faEye} className="isNotActive" />;
 
         return (
             <div className="lightTools">
                 <TreeItemLabelComponent label={this.props.light.name} onClick={() => this.props.onClick()} icon={faLightbulb} color="yellow" />
-                <div className="enableLight icon" onClick={() => this.switchIsEnabled()} title="Turn on/off the light">
+                <div className="visibility icon" onClick={() => this.switchIsEnabled()} title="Turn on/off the light">
                     {isEnabledElement}
                 </div>
+                <div className="enableGizmo icon" onClick={() => this.toggleGizmo()} title="Turn on/off the light's gizmo">
+                    {isGizmoEnabled}
+                </div>
                 {
                     <ExtensionsComponent target={this.props.light} extensibilityGroups={this.props.extensibilityGroups} />
                 }

+ 55 - 2
inspector/src/components/sceneExplorer/entities/sceneTreeItemComponent.tsx

@@ -10,15 +10,20 @@ import { faSyncAlt, faImage, faCrosshairs, faArrowsAlt, faCompress, faRedoAlt }
 import { ExtensionsComponent } from "../extensionsComponent";
 import * as React from "react";
 
+import { GlobalState } from "../../globalState";
+import { UtilityLayerRenderer } from 'babylonjs';
+
 interface ISceneTreeItemComponentProps {
     scene: Scene;
     onRefresh: () => void;
     selectedEntity?: any;
     extensibilityGroups?: IExplorerExtensibilityGroup[];
     onSelectionChangedObservable?: Observable<any>;
+    globalState: GlobalState;
 }
 
 export class SceneTreeItemComponent extends React.Component<ISceneTreeItemComponentProps, { isSelected: boolean, isInPickingMode: boolean, gizmoMode: number }> {
+    private _gizmoLayerOnPointerObserver: Nullable<Observer<PointerInfo>>;
     private _onPointerObserver: Nullable<Observer<PointerInfo>>;
     private _onSelectionChangeObserver: Nullable<Observer<any>>;
     private _selectedEntity: any;
@@ -67,9 +72,11 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                 const manager: GizmoManager = scene.reservedDataStore.gizmoManager;
 
                 const className = entity.getClassName();
-
+                
                 if (className === "TransformNode" || className.indexOf("Mesh") !== -1) {
                     manager.attachToMesh(entity);
+                }else if(className.indexOf("Light") !== -1 && this._selectedEntity.reservedDataStore && this._selectedEntity.reservedDataStore.lightGizmo){
+                    manager.attachToMesh(this._selectedEntity.reservedDataStore.lightGizmo.attachedMesh);
                 }
             }
         });
@@ -83,6 +90,11 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
             this._onPointerObserver = null;
         }
 
+        if (this._gizmoLayerOnPointerObserver) {
+            scene.onPointerObservable.remove(this._gizmoLayerOnPointerObserver);
+            this._gizmoLayerOnPointerObserver = null;
+        }
+
         if (this._onSelectionChangeObserver && this.props.onSelectionChangedObservable) {
             this.props.onSelectionChangedObservable.remove(this._onSelectionChangeObserver);
         }
@@ -108,10 +120,27 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
             this._onPointerObserver = scene.onPointerObservable.add(() => {
                 const pickPosition = scene.unTranslatedPointer;
                 const pickInfo = scene.pick(pickPosition.x, pickPosition.y, (mesh) => mesh.isEnabled() && mesh.isVisible && mesh.getTotalVertices() > 0);
-
+                
+                // Pick light gizmos first
+                if(this.props.globalState.lightGizmos.length > 0){
+                    var gizmoScene = this.props.globalState.lightGizmos[0].gizmoLayer.utilityLayerScene;
+                    let pickInfo = gizmoScene.pick(pickPosition.x, pickPosition.y, (m:any)=>{
+                        for(var g of (this.props.globalState.lightGizmos as any)){
+                            if(g.attachedMesh == m){
+                                return true;
+                            }
+                        }
+                        return false;
+                    });
+                    if (pickInfo && pickInfo.hit && this.props.onSelectionChangedObservable) {
+                        this.props.onSelectionChangedObservable.notifyObservers(pickInfo.pickedMesh);
+                        return;
+                    }
+                }
                 if (pickInfo && pickInfo.hit && this.props.onSelectionChangedObservable) {
                     this.props.onSelectionChangedObservable.notifyObservers(pickInfo.pickedMesh);
                 }
+
             }, PointerEventTypes.POINTERTAP);
         }
 
@@ -125,11 +154,33 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
             scene.reservedDataStore = {};
         }
 
+        if (this._gizmoLayerOnPointerObserver) {
+            scene.onPointerObservable.remove(this._gizmoLayerOnPointerObserver);
+            this._gizmoLayerOnPointerObserver = null;
+        }
+
         if (!scene.reservedDataStore.gizmoManager) {
             scene.reservedDataStore.gizmoManager = new GizmoManager(scene);
         }
 
         const manager: GizmoManager = scene.reservedDataStore.gizmoManager;
+        // Allow picking of light gizmo when a gizmo mode is selected
+        this._gizmoLayerOnPointerObserver = UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene.onPointerObservable.add((pointerInfo)=>{
+            if (pointerInfo.type == PointerEventTypes.POINTERDOWN) {
+                if (pointerInfo.pickInfo && pointerInfo.pickInfo.pickedMesh) {
+                    var node: Nullable<any> = pointerInfo.pickInfo.pickedMesh;
+                    // Attach to the most parent node
+                    while (node && node.parent != null) {
+                        node = node.parent;
+                    }
+                    for(var gizmo of this.props.globalState.lightGizmos){
+                        if(gizmo._rootMesh == node){
+                            manager.attachToMesh(gizmo.attachedMesh);
+                        }
+                    }
+                }
+            }
+        })
 
         manager.positionGizmoEnabled = false;
         manager.rotationGizmoEnabled = false;
@@ -157,6 +208,8 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
 
                 if (className === "TransformNode" || className.indexOf("Mesh") !== -1) {
                     manager.attachToMesh(this._selectedEntity);
+                } else if(className.indexOf("Light") !== -1 && this._selectedEntity.reservedDataStore && this._selectedEntity.reservedDataStore.lightGizmo){
+                    manager.attachToMesh(this._selectedEntity.reservedDataStore.lightGizmo.attachedMesh);
                 }
             }
         }

+ 1 - 1
inspector/src/components/sceneExplorer/sceneExplorer.scss

@@ -373,7 +373,7 @@
         .lightTools {
             grid-column: 2;
             display: grid;
-            grid-template-columns: 1fr 20px auto 5px;
+            grid-template-columns: 1fr 20px 20px auto 5px;
             align-items: center;
 
             .enableLight {

+ 1 - 1
inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx

@@ -207,7 +207,7 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
         return (
             <div id="tree">
                 <SceneExplorerFilterComponent onFilter={(filter) => this.filterContent(filter)} />
-                <SceneTreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} scene={scene} onRefresh={() => this.forceUpdate()} onSelectionChangedObservable={this.props.globalState.onSelectionChangedObservable} />
+                <SceneTreeItemComponent globalState={this.props.globalState} extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} scene={scene} onRefresh={() => this.forceUpdate()} onSelectionChangedObservable={this.props.globalState.onSelectionChangedObservable} />
                 <TreeItemComponent globalState={this.props.globalState} extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.rootNodes} label="Nodes" offset={1} filter={this.state.filter} />
                 <TreeItemComponent globalState={this.props.globalState} extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.materials} label="Materials" offset={1} filter={this.state.filter} />
                 <TreeItemComponent globalState={this.props.globalState} extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={textures} label="Textures" offset={1} filter={this.state.filter} />

+ 17 - 1
inspector/src/inspector.ts

@@ -404,6 +404,11 @@ export class Inspector {
                 this._CreateActionTabs(scene, options, parentControl);
             }
         }
+
+        // Light gizmos
+        scene.lights.forEach((l)=>{
+            this._GlobalState.enableLightGizmo(l, true);
+        });
     }
 
     private static _CreateCanvasContainer(parentControl: HTMLElement) {
@@ -443,6 +448,17 @@ export class Inspector {
             return;
         }
 
+        // Gizmo disposal
+        this._GlobalState.lightGizmos.forEach((g)=>{
+            if(g.light){
+                this._GlobalState.enableLightGizmo(g.light, false);
+            }
+        })
+        if(this._Scene.reservedDataStore && this._Scene.reservedDataStore.gizmoManager){
+            this._Scene.reservedDataStore.gizmoManager.dispose();
+            this._Scene.reservedDataStore.gizmoManager = null;
+        }
+
         if (this._NewCanvasContainer) {
             this._DestroyCanvasContainer();
         }
@@ -489,7 +505,7 @@ export class Inspector {
                 this._EmbedHost.parentElement.removeChild(this._EmbedHost);
             }
             this._EmbedHost = null;
-        }
+        }        
 
         Inspector._OpenedPane = 0;
         this._Cleanup();

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

@@ -79,7 +79,7 @@ mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)
 }
 
 vec3 perturbNormal(vec3 viewDir, vec3 mixColor)
-{	
+{
 	vec3 bump1Color = texture2D(bump1Sampler, vTextureUV * diffuse1Infos).xyz;
 	vec3 bump2Color = texture2D(bump2Sampler, vTextureUV * diffuse2Infos).xyz;
 	vec3 bump3Color = texture2D(bump3Sampler, vTextureUV * diffuse3Infos).xyz;

+ 28 - 7
materialsLibrary/src/terrain/terrainMaterial.ts

@@ -144,16 +144,37 @@ export class TerrainMaterial extends PushMaterial {
 
         // Textures
         if (scene.texturesEnabled) {
-            if (this.mixTexture && MaterialFlags.DiffuseTextureEnabled) {
-                if (!this.mixTexture.isReady()) {
+            if (!this.mixTexture || !this.mixTexture.isReady()) {
+                return false;
+            }
+
+            defines._needUVs = true;
+
+            if (MaterialFlags.DiffuseTextureEnabled) {
+                if (!this.diffuseTexture1 || !this.diffuseTexture1.isReady()) {
+                    return false;
+                }
+                if (!this.diffuseTexture2 || !this.diffuseTexture2.isReady()) {
+                    return false;
+                }
+                if (!this.diffuseTexture3 || !this.diffuseTexture3.isReady()) {
                     return false;
-                } else {
-                    defines._needUVs = true;
-                    defines.DIFFUSE = true;
                 }
+
+                defines.DIFFUSE = true;
             }
-            if ((this.bumpTexture1 || this.bumpTexture2 || this.bumpTexture3) && MaterialFlags.BumpTextureEnabled) {
-                defines._needUVs = true;
+
+            if (this.bumpTexture1 && this.bumpTexture2 && this.bumpTexture3 && MaterialFlags.BumpTextureEnabled) {
+                if (!this.bumpTexture1.isReady()) {
+                    return false;
+                }
+                if (!this.bumpTexture2.isReady()) {
+                    return false;
+                }
+                if (!this.bumpTexture3.isReady()) {
+                    return false;
+                }
+
                 defines._needNormals = true;
                 defines.BUMP = true;
             }

+ 1 - 1
package.json

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

+ 8 - 2
src/Cameras/VR/vrExperienceHelper.ts

@@ -607,6 +607,12 @@ export class VRExperienceHelper {
     }
 
     /**
+     * Defines wether or not Pointer lock should be requested when switching to
+     * full screen.
+     */
+    public requestPointerLockOnFullScreen = true;
+
+    /**
      * Instantiates a VRExperienceHelper.
      * Helps to quickly add VR support to an existing scene.
      * @param scene The scene the VRExperienceHelper belongs to.
@@ -756,7 +762,7 @@ export class VRExperienceHelper {
             if (this.isInVRMode) {
                 this.exitVR();
                 if (this._fullscreenVRpresenting) {
-                    this._scene.getEngine().switchFullscreen(true);
+                    this._scene.getEngine().exitFullscreen();
                 }
             }
         }, PointerEventTypes.POINTERDOUBLETAP, false);
@@ -970,7 +976,7 @@ export class VRExperienceHelper {
                 this._vrDeviceOrientationCamera.minZ = this._scene.activeCamera.minZ;
             }
             this._scene.activeCamera = this._vrDeviceOrientationCamera;
-            this._scene.getEngine().switchFullscreen(true);
+            this._scene.getEngine().enterFullscreen(this.requestPointerLockOnFullScreen);
             this.updateButtonVisibility();
         }
 

+ 21 - 2
src/Engines/engine.ts

@@ -491,7 +491,7 @@ export class Engine {
      * Returns the current version of the framework
      */
     public static get Version(): string {
-        return "4.0.0-alpha.21";
+        return "4.0.0-alpha.22";
     }
 
     /**
@@ -1983,8 +1983,18 @@ export class Engine {
      */
     public switchFullscreen(requestPointerLock: boolean): void {
         if (this.isFullscreen) {
-            Tools.ExitFullscreen();
+            this.exitFullscreen();
         } else {
+            this.enterFullscreen(requestPointerLock);
+        }
+    }
+
+    /**
+     * Enters full screen mode
+     * @param requestPointerLock defines if a pointer lock should be requested from the user
+     */
+    public enterFullscreen(requestPointerLock: boolean): void {
+        if (!this.isFullscreen) {
             this._pointerLockRequested = requestPointerLock;
             if (this._renderingCanvas) {
                 Tools.RequestFullscreen(this._renderingCanvas);
@@ -1993,6 +2003,15 @@ export class Engine {
     }
 
     /**
+     * Exits full screen mode
+     */
+    public exitFullscreen(): void {
+        if (this.isFullscreen) {
+            Tools.ExitFullscreen();
+        }
+    }
+
+    /**
      * Clear the current render buffer or the current render target (if any is set up)
      * @param color defines the color to use
      * @param backBuffer defines if the back buffer must be cleared

+ 1 - 1
src/Gizmos/gizmo.ts

@@ -15,7 +15,7 @@ export class Gizmo implements IDisposable {
     /**
      * The root mesh of the gizmo
      */
-    protected _rootMesh: Mesh;
+    public _rootMesh: Mesh;
     private _attachedMesh: Nullable<AbstractMesh>;
     /**
      * Ratio for the scale of the gizmo (Default: 1)

+ 2 - 1
src/Gizmos/index.ts

@@ -6,4 +6,5 @@ export * from "./gizmoManager";
 export * from "./planeRotationGizmo";
 export * from "./positionGizmo";
 export * from "./rotationGizmo";
-export * from "./scaleGizmo";
+export * from "./scaleGizmo";
+export * from "./lightGizmo";

+ 70 - 0
src/Gizmos/lightGizmo.ts

@@ -0,0 +1,70 @@
+import { Nullable } from "../types";
+import { Color3 } from "../Maths/math";
+import { AbstractMesh } from "../Meshes/abstractMesh";
+import { Mesh } from "../Meshes/mesh";
+import { Gizmo } from "./gizmo";
+import { UtilityLayerRenderer } from "../Rendering/utilityLayerRenderer";
+
+import { StandardMaterial } from '../Materials/standardMaterial';
+import { Light } from '../Lights/light';
+
+/**
+ * Gizmo that enables viewing a light
+ */
+export class LightGizmo extends Gizmo {
+    private _box: Mesh;
+
+    /**
+     * Creates a LightGizmo
+     * @param gizmoLayer The utility layer the gizmo will be added to
+     */
+    constructor(gizmoLayer?: UtilityLayerRenderer) {
+        super(gizmoLayer);
+        this._box = Mesh.CreateCylinder("light", 0.02, 0, 0.02, 16, 1, this.gizmoLayer.utilityLayerScene);
+        this._box.rotation.x = -Math.PI / 2;
+        this._box.bakeCurrentTransformIntoVertices();
+        this._box.material = new StandardMaterial("", this.gizmoLayer.utilityLayerScene);
+        (this._box.material as StandardMaterial).emissiveColor = Color3.Yellow();
+        this._rootMesh.addChild(this._box);
+        this.attachedMesh = new AbstractMesh("", this.gizmoLayer.utilityLayerScene);
+    }
+    private _light: Nullable<Light> = null;
+
+    /**
+     * The light that the gizmo is attached to
+     */
+    public set light(light: Nullable<Light>) {
+        this._light = light;
+        if ((light as any).position) {
+            this.attachedMesh!.position.copyFrom((light as any).position);
+        }
+        if ((light as any).direction) {
+            this._box.setDirection((light as any).direction);
+        }
+    }
+    public get light() {
+        return this._light;
+    }
+
+    /**
+     * @hidden
+     * Updates the gizmo to match the attached mesh's position/rotation
+     */
+    protected _update() {
+        super._update();
+        if (!this._light) {
+            return;
+        }
+        if ((this._light as any).position) {
+            (this._light as any).position.copyFrom(this.attachedMesh!.position);
+        }
+        if ((this._light as any).direction) {
+            (this._light as any).direction.copyFrom(this._box.forward);
+        }
+        if (!this._light.isEnabled()) {
+            (this._box.material as StandardMaterial).emissiveColor.set(0, 0, 0);
+        } else {
+            (this._box.material as StandardMaterial).emissiveColor.set(1, 1, 1);
+        }
+    }
+}

+ 1 - 1
src/Lights/shadowLight.ts

@@ -265,7 +265,7 @@ export abstract class ShadowLight extends Light implements IShadowLight {
 
     /**
      * Sets the ShadowLight direction toward the passed target.
-     * @param target The point tot target in local space
+     * @param target The point to target in local space
      * @returns the updated ShadowLight direction
      */
     public setDirectionToTarget(target: Vector3): Vector3 {