Browse Source

Merge pull request #8717 from BabylonJS/master

Nightly
mergify[bot] 5 years ago
parent
commit
e6a0bc9380
68 changed files with 4252 additions and 681 deletions
  1. 286 44
      dist/preview release/babylon.d.ts
  2. 2 2
      dist/preview release/babylon.js
  3. 980 95
      dist/preview release/babylon.max.js
  4. 1 1
      dist/preview release/babylon.max.js.map
  5. 597 92
      dist/preview release/babylon.module.d.ts
  6. 286 44
      dist/preview release/documentation.d.ts
  7. 48 48
      dist/preview release/gui/babylon.gui.js
  8. 1 1
      dist/preview release/gui/babylon.gui.js.map
  9. 4 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  10. 137 36
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  11. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  12. 5 0
      dist/preview release/inspector/babylon.inspector.d.ts
  13. 13 0
      dist/preview release/inspector/babylon.inspector.module.d.ts
  14. 1 1
      dist/preview release/packagesSizeBaseLine.json
  15. 597 92
      dist/preview release/viewer/babylon.module.d.ts
  16. 103 99
      dist/preview release/viewer/babylon.viewer.js
  17. 1 1
      dist/preview release/viewer/babylon.viewer.max.js
  18. 4 1
      dist/preview release/what's new.md
  19. 21 0
      inspector/src/components/globalState.ts
  20. 24 5
      inspector/src/components/sceneExplorer/entities/cameraTreeItemComponent.tsx
  21. 78 23
      inspector/src/components/sceneExplorer/entities/sceneTreeItemComponent.tsx
  22. 6 2
      inspector/src/components/sceneExplorer/sceneExplorer.scss
  23. 1 1
      inspector/src/components/sceneExplorer/treeItemSpecializedComponent.tsx
  24. 5 0
      inspector/src/inspector.ts
  25. 1 1
      src/Engines/thinEngine.ts
  26. 190 0
      src/Gizmos/cameraGizmo.ts
  27. 72 10
      src/Gizmos/gizmoManager.ts
  28. 1 0
      src/Gizmos/index.ts
  29. 14 0
      src/Loading/Plugins/babylonFileLoader.ts
  30. 14 0
      src/Meshes/instancedMesh.ts
  31. 6 2
      src/Misc/sceneRecorder.ts
  32. 6 0
      src/Misc/sceneSerializer.ts
  33. 2 2
      src/Particles/gpuParticleSystem.ts
  34. 11 0
      src/PostProcesses/anaglyphPostProcess.ts
  35. 26 0
      src/PostProcesses/blackAndWhitePostProcess.ts
  36. 18 1
      src/PostProcesses/bloomMergePostProcess.ts
  37. 33 2
      src/PostProcesses/blurPostProcess.ts
  38. 43 0
      src/PostProcesses/chromaticAberrationPostProcess.ts
  39. 16 0
      src/PostProcesses/circleOfConfusionPostProcess.ts
  40. 34 0
      src/PostProcesses/colorCorrectionPostProcess.ts
  41. 31 3
      src/PostProcesses/convolutionPostProcess.ts
  42. 21 1
      src/PostProcesses/depthOfFieldBlurPostProcess.ts
  43. 8 0
      src/PostProcesses/depthOfFieldMergePostProcess.ts
  44. 25 0
      src/PostProcesses/displayPassPostProcess.ts
  45. 15 0
      src/PostProcesses/extractHighlightsPostProcess.ts
  46. 31 2
      src/PostProcesses/filterPostProcess.ts
  47. 23 4
      src/PostProcesses/fxaaPostProcess.ts
  48. 27 0
      src/PostProcesses/grainPostProcess.ts
  49. 8 0
      src/PostProcesses/highlightsPostProcess.ts
  50. 0 1
      src/PostProcesses/imageProcessingPostProcess.ts
  51. 26 1
      src/PostProcesses/motionBlurPostProcess.ts
  52. 44 0
      src/PostProcesses/passPostProcess.ts
  53. 93 31
      src/PostProcesses/postProcess.ts
  54. 51 6
      src/PostProcesses/refractionPostProcess.ts
  55. 26 1
      src/PostProcesses/screenSpaceCurvaturePostProcess.ts
  56. 25 2
      src/PostProcesses/screenSpaceReflectionPostProcess.ts
  57. 28 0
      src/PostProcesses/sharpenPostProcess.ts
  58. 16 0
      src/PostProcesses/stereoscopicInterlacePostProcess.ts
  59. 7 5
      src/PostProcesses/subSurfaceScatteringPostProcess.ts
  60. 7 0
      src/PostProcesses/tonemapPostProcess.ts
  61. 3 0
      src/PostProcesses/volumetricLightScatteringPostProcess.ts
  62. 8 0
      src/PostProcesses/vrDistortionCorrectionPostProcess.ts
  63. 8 0
      src/PostProcesses/vrMultiviewToSingleviewPostProcess.ts
  64. 6 0
      src/abstractScene.ts
  65. 1 1
      src/node.ts
  66. 23 10
      src/scene.ts
  67. 2 2
      tests/es6Modules/webpack-stats.json
  68. BIN
      tests/validation/ReferenceImages/highlights.png

+ 286 - 44
dist/preview release/babylon.d.ts

@@ -16332,6 +16332,8 @@ declare module BABYLON {
         _syncSubMeshes(): InstancedMesh;
         /** @hidden */
         _generatePointsArray(): boolean;
+        /** @hidden */
+        _updateBoundingInfo(): AbstractMesh;
         /**
          * Creates a new InstancedMesh from the current mesh.
          * - name (string) : the cloned mesh name
@@ -19692,6 +19694,11 @@ declare module BABYLON {
      */
     export class VRMultiviewToSingleviewPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "VRMultiviewToSingleviewPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes a VRMultiviewToSingleview
          * @param name name of the post process
          * @param camera camera to be applied to
@@ -22527,12 +22534,12 @@ declare module BABYLON {
      * See https://doc.babylonjs.com/how_to/how_to_use_postprocesses
      */
     export class PostProcess {
-        /** Name of the PostProcess. */
-        name: string;
         /**
          * Gets or sets the unique id of the post process
          */
         uniqueId: number;
+        /** Name of the PostProcess. */
+        name: string;
         /**
         * Width of the texture to apply the post process on
         */
@@ -22731,11 +22738,9 @@ declare module BABYLON {
          * @param blockCompilation If the shader should not be compiled imediatly. (default: false)
          * @param textureFormat Format of textures used when performing the post process. (default: TEXTUREFORMAT_RGBA)
          */
-        constructor(
-        /** Name of the PostProcess. */
-        name: string, fragmentUrl: string, parameters: Nullable<string[]>, samplers: Nullable<string[]>, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, defines?: Nullable<string>, textureType?: number, vertexUrl?: string, indexParameters?: any, blockCompilation?: boolean, textureFormat?: number);
+        constructor(name: string, fragmentUrl: string, parameters: Nullable<string[]>, samplers: Nullable<string[]>, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, defines?: Nullable<string>, textureType?: number, vertexUrl?: string, indexParameters?: any, blockCompilation?: boolean, textureFormat?: number);
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "PostProcess" string
          */
         getClassName(): string;
@@ -22812,6 +22817,19 @@ declare module BABYLON {
          * @param camera The camera to dispose the post process on.
          */
         dispose(camera?: Camera): void;
+        /**
+         * Serializes the particle system to a JSON object
+         * @returns the JSON object
+         */
+        serialize(): any;
+        /**
+         * Creates a material from parsed material data
+         * @param parsedPostProcess defines parsed post process data
+         * @param scene defines the hosting scene
+         * @param rootUrl defines the root URL to use to load textures
+         * @returns a new post process
+         */
+        static Parse(parsedPostProcess: any, scene: Scene, rootUrl: string): Nullable<PostProcess>;
     }
 }
 declare module BABYLON {
@@ -22862,13 +22880,13 @@ declare module BABYLON {
      * Can be used twice in x and y directions to perform a guassian blur in two passes.
      */
     export class BlurPostProcess extends PostProcess {
-        /** The direction in which to blur the image. */
-        direction: Vector2;
         private blockCompilation;
         protected _kernel: number;
         protected _idealKernel: number;
         protected _packedFloat: boolean;
         private _staticDefines;
+        /** The direction in which to blur the image. */
+        direction: Vector2;
         /**
          * Sets the length in pixels of the blur sample region
          */
@@ -22886,6 +22904,11 @@ declare module BABYLON {
          */
         get packedFloat(): boolean;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "BlurPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance BlurPostProcess
          * @param name The name of the effect.
          * @param direction The direction in which to blur the image.
@@ -22898,9 +22921,7 @@ declare module BABYLON {
          * @param textureType Type of textures used when performing the post process. (default: 0)
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
-        constructor(name: string, 
-        /** The direction in which to blur the image. */
-        direction: Vector2, kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, defines?: string, blockCompilation?: boolean);
+        constructor(name: string, direction: Vector2, kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, defines?: string, blockCompilation?: boolean);
         /**
          * Updates the effect with the current post process compile time values and recompiles the shader.
          * @param defines Define statements that should be added at the beginning of the shader. (default: null)
@@ -22935,6 +22956,8 @@ declare module BABYLON {
           * @return GLSL float string.
           */
         protected _glslFloat(x: number, decimalFigures?: number): string;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<BlurPostProcess>;
     }
 }
 declare module BABYLON {
@@ -24186,10 +24209,11 @@ declare module BABYLON {
      * Sub surface scattering post process
      */
     export class SubSurfaceScatteringPostProcess extends PostProcess {
-        /** @hidden */
-        texelWidth: number;
-        /** @hidden */
-        texelHeight: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "SubSurfaceScatteringPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
     }
 }
@@ -32979,7 +33003,7 @@ declare module BABYLON {
         get animationPropertiesOverride(): Nullable<AnimationPropertiesOverride>;
         set animationPropertiesOverride(value: Nullable<AnimationPropertiesOverride>);
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "Node" string
          */
         getClassName(): string;
@@ -35390,7 +35414,7 @@ declare module BABYLON {
          */
         get webGLVersion(): number;
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "Engine" string
          */
         getClassName(): string;
@@ -39839,10 +39863,6 @@ declare module BABYLON {
         */
         postProcessesEnabled: boolean;
         /**
-         * The list of postprocesses added to the scene
-         */
-        postProcesses: PostProcess[];
-        /**
          * Gets the current postprocess manager
          */
         postProcessManager: PostProcessManager;
@@ -40111,7 +40131,7 @@ declare module BABYLON {
          */
         constructor(engine: Engine, options?: SceneOptions);
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "Scene" string
          */
         getClassName(): string;
@@ -40789,6 +40809,12 @@ declare module BABYLON {
          */
         getMorphTargetByName(name: string): Nullable<MorphTarget>;
         /**
+         * Gets a post process using a given name (if many are found, this function will pick the first one)
+         * @param name defines the name to search for
+         * @return the found post process or null if not found at all.
+         */
+        getPostProcessByName(name: string): Nullable<PostProcess>;
+        /**
          * Gets a boolean indicating if the given mesh is active
          * @param mesh defines the mesh to look for
          * @returns true if the mesh is in the active list
@@ -41336,6 +41362,10 @@ declare module BABYLON {
          */
         environmentTexture: Nullable<BaseTexture>;
         /**
+         * The list of postprocesses added to the scene
+         */
+        postProcesses: PostProcess[];
+        /**
          * @returns all meshes, lights, cameras, transformNodes and bones
          */
         getNodes(): Array<Node>;
@@ -45939,6 +45969,11 @@ declare module BABYLON {
      */
     export class PassPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "PassPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates the PassPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -45950,6 +45985,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): PassPostProcess;
     }
     /**
      * PassCubePostProcess which produces an output the same as it's input (which must be a cube texture)
@@ -45968,6 +46005,11 @@ declare module BABYLON {
         get face(): number;
         set face(value: number);
         /**
+         * Gets a string identifying the name of the class
+         * @returns "PassCubePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates the PassCubePostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -45979,6 +46021,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): PassCubePostProcess;
     }
 }
 declare module BABYLON {
@@ -45995,6 +46039,11 @@ declare module BABYLON {
     export class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "AnaglyphPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new AnaglyphPostProcess
          * @param name defines postprocess name
          * @param options defines creation options or target ratio scale
@@ -46324,6 +46373,11 @@ declare module BABYLON {
         private _scaleFactor;
         private _lensCenter;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "VRDistortionCorrectionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes the VRDistortionCorrectionPostProcess
          * @param name The name of the effect.
          * @param camera The camera to apply the render pass to.
@@ -50782,7 +50836,7 @@ declare module BABYLON {
         private _renderLine;
         private _renderFunction;
         private _scene;
-        private _updateToMeshFunction;
+        private _onAfterRenderObserver;
         private _onAfterStepObserver;
         private _attachedToMesh;
         private _meshSpaceDirection;
@@ -53612,7 +53666,7 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Helps setup gizmo's in the scene to rotate/scale/position meshes
+     * Helps setup gizmo's in the scene to rotate/scale/position nodes
      */
     export class GizmoManager implements IDisposable {
         private scene;
@@ -53629,9 +53683,12 @@ declare module BABYLON {
         clearGizmoOnEmptyPointerEvent: boolean;
         /** Fires an event when the manager is attached to a mesh */
         onAttachedToMeshObservable: Observable<Nullable<AbstractMesh>>;
+        /** Fires an event when the manager is attached to a node */
+        onAttachedToNodeObservable: Observable<Nullable<Node>>;
         private _gizmosEnabled;
         private _pointerObserver;
         private _attachedMesh;
+        private _attachedNode;
         private _boundingBoxColor;
         private _defaultUtilityLayer;
         private _defaultKeepDepthUtilityLayer;
@@ -53645,7 +53702,11 @@ declare module BABYLON {
          */
         attachableMeshes: Nullable<Array<AbstractMesh>>;
         /**
-         * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh. (Default: true)
+         * Array of nodes which will have the gizmo attached when a pointer selected them. If null, all nodes are attachable. (Default: null)
+         */
+        attachableNodes: Nullable<Array<Node>>;
+        /**
+         * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh/attachToNode. (Default: true)
          */
         usePointerToAttachGizmos: boolean;
         /**
@@ -53668,6 +53729,11 @@ declare module BABYLON {
          */
         attachToMesh(mesh: Nullable<AbstractMesh>): void;
         /**
+         * Attaches a set of gizmos to the specified node
+         * @param node The node the gizmo's should be attached to
+         */
+        attachToNode(node: Nullable<Node>): void;
+        /**
          * If the position gizmo is enabled
          */
         set positionGizmoEnabled(value: boolean);
@@ -54037,6 +54103,47 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /**
+     * Gizmo that enables viewing a camera
+     */
+    export class CameraGizmo extends Gizmo {
+        private _cameraMesh;
+        private _cameraLinesMesh;
+        private _material;
+        /**
+         * Creates a CameraGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _camera;
+        /** Gets or sets a boolean indicating if frustum lines must be rendered (true by default)) */
+        get displayFrustum(): boolean;
+        set displayFrustum(value: boolean);
+        /**
+         * The camera that the gizmo is attached to
+         */
+        set camera(camera: Nullable<Camera>);
+        get camera(): Nullable<Camera>;
+        /**
+         * Gets the material used to render the camera gizmo
+         */
+        get material(): StandardMaterial;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+        private static _Scale;
+        private _invProjection;
+        /**
+         * Disposes of the camera gizmo
+         */
+        dispose(): void;
+        private static _CreateCameraMesh;
+        private static _CreateCameraFrustum;
+    }
+}
+declare module BABYLON {
     /** @hidden */
     export var backgroundFragmentDeclaration: {
         name: string;
@@ -68631,6 +68738,11 @@ declare module BABYLON {
          */
         degree: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "BlackAndWhitePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a black and white post process
          * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#black-and-white
          * @param name The name of the effect.
@@ -68641,6 +68753,8 @@ declare module BABYLON {
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<BlackAndWhitePostProcess>;
     }
 }
 declare module BABYLON {
@@ -68757,6 +68871,11 @@ declare module BABYLON {
          * @hidden
          */
         _inputPostProcess: Nullable<PostProcess>;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "ExtractHighlightsPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
     }
 }
@@ -68775,6 +68894,11 @@ declare module BABYLON {
         /** Weight of the bloom to be added to the original input. */
         weight: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "BloomMergePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of @see BloomMergePostProcess
          * @param name The name of the effect.
          * @param originalFromInput Post process which's input will be used for the merge.
@@ -68880,6 +69004,15 @@ declare module BABYLON {
          * The center position where the radialIntensity should be around. [0.5,0.5 is center of screen, 1,1 is top right corder] (default: Vector2(0.5 ,0.5))
          */
         centerPosition: Vector2;
+        /** The width of the screen to apply the effect on */
+        screenWidth: number;
+        /** The height of the screen to apply the effect on */
+        screenHeight: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "ChromaticAberrationPostProcess" string
+         */
+        getClassName(): string;
         /**
          * Creates a new instance ChromaticAberrationPostProcess
          * @param name The name of the effect.
@@ -68894,6 +69027,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, screenWidth: number, screenHeight: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ChromaticAberrationPostProcess>;
     }
 }
 declare module BABYLON {
@@ -68924,6 +69059,11 @@ declare module BABYLON {
          * Focal length of the effect's camera in scene units/1000 (eg. millimeter). (default: 50)
          */
         focalLength: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "CircleOfConfusionPostProcess" string
+         */
+        getClassName(): string;
         private _depthTexture;
         /**
          * Creates a new instance CircleOfConfusionPostProcess
@@ -68969,7 +69109,18 @@ declare module BABYLON {
      */
     export class ColorCorrectionPostProcess extends PostProcess {
         private _colorTableTexture;
+        /**
+         * Gets the color table url used to create the LUT texture
+         */
+        colorTableUrl: string;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "ColorCorrectionPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, colorTableUrl: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ColorCorrectionPostProcess>;
     }
 }
 declare module BABYLON {
@@ -68989,6 +69140,11 @@ declare module BABYLON {
         /** Array of 9 values corresponding to the 3x3 kernel to be applied */
         kernel: number[];
         /**
+         * Gets a string identifying the name of the class
+         * @returns "ConvolutionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance ConvolutionPostProcess
          * @param name The name of the effect.
          * @param kernel Array of 9 values corresponding to the 3x3 kernel to be applied
@@ -68999,9 +69155,9 @@ declare module BABYLON {
          * @param reusable If the post process can be reused on the same frame. (default: false)
          * @param textureType Type of textures used when performing the post process. (default: 0)
          */
-        constructor(name: string, 
-        /** Array of 9 values corresponding to the 3x3 kernel to be applied */
-        kernel: number[], options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
+        constructor(name: string, kernel: number[], options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ConvolutionPostProcess>;
         /**
          * Edge detection 0 see https://en.wikipedia.org/wiki/Kernel_(image_processing)
          */
@@ -69036,8 +69192,16 @@ declare module BABYLON {
      * See section 2.6.2 http://fileadmin.cs.lth.se/cs/education/edan35/lectures/12dof.pdf
      */
     export class DepthOfFieldBlurPostProcess extends BlurPostProcess {
+        /**
+         * The direction the blur should be applied
+         */
         direction: Vector2;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "DepthOfFieldBlurPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance CircleOfConfusionPostProcess
          * @param name The name of the effect.
          * @param scene The scene the effect belongs to.
@@ -69093,6 +69257,11 @@ declare module BABYLON {
     export class DepthOfFieldMergePostProcess extends PostProcess {
         private blurSteps;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "DepthOfFieldMergePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of DepthOfFieldMergePostProcess
          * @param name The name of the effect.
          * @param originalFromInput Post process which's input will be used for the merge.
@@ -69219,6 +69388,11 @@ declare module BABYLON {
      */
     export class DisplayPassPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "DisplayPassPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates the DisplayPassPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -69228,6 +69402,8 @@ declare module BABYLON {
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<DisplayPassPostProcess>;
     }
 }
 declare module BABYLON {
@@ -69245,6 +69421,11 @@ declare module BABYLON {
         /** The matrix to be applied to the image */
         kernelMatrix: Matrix;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "FilterPostProcess" string
+         */
+        getClassName(): string;
+        /**
          *
          * @param name The name of the effect.
          * @param kernelMatrix The matrix to be applied to the image
@@ -69254,9 +69435,9 @@ declare module BABYLON {
          * @param engine The engine which the post process will be applied. (default: current engine)
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
-        constructor(name: string, 
-        /** The matrix to be applied to the image */
-        kernelMatrix: Matrix, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        constructor(name: string, kernelMatrix: Matrix, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<FilterPostProcess>;
     }
 }
 declare module BABYLON {
@@ -69279,12 +69460,15 @@ declare module BABYLON {
      * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#fxaa
      */
     export class FxaaPostProcess extends PostProcess {
-        /** @hidden */
-        texelWidth: number;
-        /** @hidden */
-        texelHeight: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "FxaaPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
         private _getDefines;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): FxaaPostProcess;
     }
 }
 declare module BABYLON {
@@ -69308,6 +69492,11 @@ declare module BABYLON {
          */
         animated: boolean;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "GrainPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of @see GrainPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -69319,6 +69508,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): GrainPostProcess;
     }
 }
 declare module BABYLON {
@@ -69335,6 +69526,11 @@ declare module BABYLON {
      */
     export class HighlightsPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "HighlightsPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Extracts highlights from the image
          * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses
          * @param name The name of the effect.
@@ -69602,6 +69798,11 @@ declare module BABYLON {
         private _motionBlurSamples;
         private _geometryBufferRenderer;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "MotionBlurPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance MotionBlurPostProcess
          * @param name The name of the effect.
          * @param scene The scene containing the objects to blur according to their velocity.
@@ -69631,6 +69832,8 @@ declare module BABYLON {
          * @param camera The camera to dispose the post process on.
          */
         dispose(camera?: Camera): void;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<MotionBlurPostProcess>;
     }
 }
 declare module BABYLON {
@@ -69646,14 +69849,16 @@ declare module BABYLON {
      * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#refraction
      */
     export class RefractionPostProcess extends PostProcess {
+        private _refTexture;
+        private _ownRefractionTexture;
         /** the base color of the refraction (used to taint the rendering) */
         color: Color3;
         /** simulated refraction depth */
         depth: number;
         /** the coefficient of the base color (0 to remove base color tainting) */
         colorLevel: number;
-        private _refTexture;
-        private _ownRefractionTexture;
+        /** Gets the url used to load the refraction texture */
+        refractionTextureUrl: string;
         /**
          * Gets or sets the refraction texture
          * Please note that you are responsible for disposing the texture if you set it manually
@@ -69661,6 +69866,11 @@ declare module BABYLON {
         get refractionTexture(): Texture;
         set refractionTexture(value: Texture);
         /**
+         * Gets a string identifying the name of the class
+         * @returns "RefractionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes the RefractionPostProcess
          * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#refraction
          * @param name The name of the effect.
@@ -69674,18 +69884,14 @@ declare module BABYLON {
          * @param engine The engine which the post process will be applied. (default: current engine)
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
-        constructor(name: string, refractionTextureUrl: string, 
-        /** the base color of the refraction (used to taint the rendering) */
-        color: Color3, 
-        /** simulated refraction depth */
-        depth: number, 
-        /** the coefficient of the base color (0 to remove base color tainting) */
-        colorLevel: number, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        constructor(name: string, refractionTextureUrl: string, color: Color3, depth: number, colorLevel: number, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
         /**
          * Disposes of the post process
          * @param camera Camera to dispose post process on
          */
         dispose(camera: Camera): void;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): RefractionPostProcess;
     }
 }
 declare module BABYLON {
@@ -69710,6 +69916,11 @@ declare module BABYLON {
          */
         edgeAmount: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "SharpenPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance ConvolutionPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -69721,6 +69932,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): SharpenPostProcess;
     }
 }
 declare module BABYLON {
@@ -70678,6 +70891,11 @@ declare module BABYLON {
         private _reflectionSamples;
         private _smoothSteps;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "ScreenSpaceReflectionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of ScreenSpaceReflectionPostProcess.
          * @param name The name of the effect.
          * @param scene The scene containing the objects to calculate reflections.
@@ -70718,6 +70936,8 @@ declare module BABYLON {
         get smoothSteps(): number;
         set smoothSteps(steps: number);
         private _updateEffectDefines;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): ScreenSpaceReflectionPostProcess;
     }
 }
 declare module BABYLON {
@@ -71106,6 +71326,11 @@ declare module BABYLON {
         private _stepSize;
         private _passedProcess;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "StereoscopicInterlacePostProcessI" string
+         */
+        getClassName(): string;
+        /**
          * Initializes a StereoscopicInterlacePostProcessI
          * @param name The name of the effect.
          * @param rigCameras The rig cameras to be appled to the post process
@@ -71124,6 +71349,11 @@ declare module BABYLON {
         private _stepSize;
         private _passedProcess;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "StereoscopicInterlacePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes a StereoscopicInterlacePostProcess
          * @param name The name of the effect.
          * @param rigCameras The rig cameras to be appled to the post process
@@ -71162,6 +71392,11 @@ declare module BABYLON {
         /** Defines the required exposure adjustement */
         exposureAdjustment: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "TonemapPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new TonemapPostProcess
          * @param name defines the name of the postprocess
          * @param _operator defines the operator to use
@@ -71327,6 +71562,11 @@ declare module BABYLON {
         valley: number;
         private _geometryBufferRenderer;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "ScreenSpaceCurvaturePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance ScreenSpaceCurvaturePostProcess
          * @param name The name of the effect.
          * @param scene The scene containing the objects to blur according to their velocity.
@@ -71343,6 +71583,8 @@ declare module BABYLON {
          * Support test.
          */
         static get IsSupported(): boolean;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): ScreenSpaceCurvaturePostProcess;
     }
 }
 declare module BABYLON {

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


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


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


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


+ 286 - 44
dist/preview release/documentation.d.ts

@@ -16332,6 +16332,8 @@ declare module BABYLON {
         _syncSubMeshes(): InstancedMesh;
         /** @hidden */
         _generatePointsArray(): boolean;
+        /** @hidden */
+        _updateBoundingInfo(): AbstractMesh;
         /**
          * Creates a new InstancedMesh from the current mesh.
          * - name (string) : the cloned mesh name
@@ -19692,6 +19694,11 @@ declare module BABYLON {
      */
     export class VRMultiviewToSingleviewPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "VRMultiviewToSingleviewPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes a VRMultiviewToSingleview
          * @param name name of the post process
          * @param camera camera to be applied to
@@ -22527,12 +22534,12 @@ declare module BABYLON {
      * See https://doc.babylonjs.com/how_to/how_to_use_postprocesses
      */
     export class PostProcess {
-        /** Name of the PostProcess. */
-        name: string;
         /**
          * Gets or sets the unique id of the post process
          */
         uniqueId: number;
+        /** Name of the PostProcess. */
+        name: string;
         /**
         * Width of the texture to apply the post process on
         */
@@ -22731,11 +22738,9 @@ declare module BABYLON {
          * @param blockCompilation If the shader should not be compiled imediatly. (default: false)
          * @param textureFormat Format of textures used when performing the post process. (default: TEXTUREFORMAT_RGBA)
          */
-        constructor(
-        /** Name of the PostProcess. */
-        name: string, fragmentUrl: string, parameters: Nullable<string[]>, samplers: Nullable<string[]>, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, defines?: Nullable<string>, textureType?: number, vertexUrl?: string, indexParameters?: any, blockCompilation?: boolean, textureFormat?: number);
+        constructor(name: string, fragmentUrl: string, parameters: Nullable<string[]>, samplers: Nullable<string[]>, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, defines?: Nullable<string>, textureType?: number, vertexUrl?: string, indexParameters?: any, blockCompilation?: boolean, textureFormat?: number);
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "PostProcess" string
          */
         getClassName(): string;
@@ -22812,6 +22817,19 @@ declare module BABYLON {
          * @param camera The camera to dispose the post process on.
          */
         dispose(camera?: Camera): void;
+        /**
+         * Serializes the particle system to a JSON object
+         * @returns the JSON object
+         */
+        serialize(): any;
+        /**
+         * Creates a material from parsed material data
+         * @param parsedPostProcess defines parsed post process data
+         * @param scene defines the hosting scene
+         * @param rootUrl defines the root URL to use to load textures
+         * @returns a new post process
+         */
+        static Parse(parsedPostProcess: any, scene: Scene, rootUrl: string): Nullable<PostProcess>;
     }
 }
 declare module BABYLON {
@@ -22862,13 +22880,13 @@ declare module BABYLON {
      * Can be used twice in x and y directions to perform a guassian blur in two passes.
      */
     export class BlurPostProcess extends PostProcess {
-        /** The direction in which to blur the image. */
-        direction: Vector2;
         private blockCompilation;
         protected _kernel: number;
         protected _idealKernel: number;
         protected _packedFloat: boolean;
         private _staticDefines;
+        /** The direction in which to blur the image. */
+        direction: Vector2;
         /**
          * Sets the length in pixels of the blur sample region
          */
@@ -22886,6 +22904,11 @@ declare module BABYLON {
          */
         get packedFloat(): boolean;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "BlurPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance BlurPostProcess
          * @param name The name of the effect.
          * @param direction The direction in which to blur the image.
@@ -22898,9 +22921,7 @@ declare module BABYLON {
          * @param textureType Type of textures used when performing the post process. (default: 0)
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
-        constructor(name: string, 
-        /** The direction in which to blur the image. */
-        direction: Vector2, kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, defines?: string, blockCompilation?: boolean);
+        constructor(name: string, direction: Vector2, kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, defines?: string, blockCompilation?: boolean);
         /**
          * Updates the effect with the current post process compile time values and recompiles the shader.
          * @param defines Define statements that should be added at the beginning of the shader. (default: null)
@@ -22935,6 +22956,8 @@ declare module BABYLON {
           * @return GLSL float string.
           */
         protected _glslFloat(x: number, decimalFigures?: number): string;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<BlurPostProcess>;
     }
 }
 declare module BABYLON {
@@ -24186,10 +24209,11 @@ declare module BABYLON {
      * Sub surface scattering post process
      */
     export class SubSurfaceScatteringPostProcess extends PostProcess {
-        /** @hidden */
-        texelWidth: number;
-        /** @hidden */
-        texelHeight: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "SubSurfaceScatteringPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
     }
 }
@@ -32979,7 +33003,7 @@ declare module BABYLON {
         get animationPropertiesOverride(): Nullable<AnimationPropertiesOverride>;
         set animationPropertiesOverride(value: Nullable<AnimationPropertiesOverride>);
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "Node" string
          */
         getClassName(): string;
@@ -35390,7 +35414,7 @@ declare module BABYLON {
          */
         get webGLVersion(): number;
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "Engine" string
          */
         getClassName(): string;
@@ -39839,10 +39863,6 @@ declare module BABYLON {
         */
         postProcessesEnabled: boolean;
         /**
-         * The list of postprocesses added to the scene
-         */
-        postProcesses: PostProcess[];
-        /**
          * Gets the current postprocess manager
          */
         postProcessManager: PostProcessManager;
@@ -40111,7 +40131,7 @@ declare module BABYLON {
          */
         constructor(engine: Engine, options?: SceneOptions);
         /**
-         * Gets a string idenfifying the name of the class
+         * Gets a string identifying the name of the class
          * @returns "Scene" string
          */
         getClassName(): string;
@@ -40789,6 +40809,12 @@ declare module BABYLON {
          */
         getMorphTargetByName(name: string): Nullable<MorphTarget>;
         /**
+         * Gets a post process using a given name (if many are found, this function will pick the first one)
+         * @param name defines the name to search for
+         * @return the found post process or null if not found at all.
+         */
+        getPostProcessByName(name: string): Nullable<PostProcess>;
+        /**
          * Gets a boolean indicating if the given mesh is active
          * @param mesh defines the mesh to look for
          * @returns true if the mesh is in the active list
@@ -41336,6 +41362,10 @@ declare module BABYLON {
          */
         environmentTexture: Nullable<BaseTexture>;
         /**
+         * The list of postprocesses added to the scene
+         */
+        postProcesses: PostProcess[];
+        /**
          * @returns all meshes, lights, cameras, transformNodes and bones
          */
         getNodes(): Array<Node>;
@@ -45939,6 +45969,11 @@ declare module BABYLON {
      */
     export class PassPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "PassPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates the PassPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -45950,6 +45985,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): PassPostProcess;
     }
     /**
      * PassCubePostProcess which produces an output the same as it's input (which must be a cube texture)
@@ -45968,6 +46005,11 @@ declare module BABYLON {
         get face(): number;
         set face(value: number);
         /**
+         * Gets a string identifying the name of the class
+         * @returns "PassCubePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates the PassCubePostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -45979,6 +46021,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): PassCubePostProcess;
     }
 }
 declare module BABYLON {
@@ -45995,6 +46039,11 @@ declare module BABYLON {
     export class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "AnaglyphPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new AnaglyphPostProcess
          * @param name defines postprocess name
          * @param options defines creation options or target ratio scale
@@ -46324,6 +46373,11 @@ declare module BABYLON {
         private _scaleFactor;
         private _lensCenter;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "VRDistortionCorrectionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes the VRDistortionCorrectionPostProcess
          * @param name The name of the effect.
          * @param camera The camera to apply the render pass to.
@@ -50782,7 +50836,7 @@ declare module BABYLON {
         private _renderLine;
         private _renderFunction;
         private _scene;
-        private _updateToMeshFunction;
+        private _onAfterRenderObserver;
         private _onAfterStepObserver;
         private _attachedToMesh;
         private _meshSpaceDirection;
@@ -53612,7 +53666,7 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Helps setup gizmo's in the scene to rotate/scale/position meshes
+     * Helps setup gizmo's in the scene to rotate/scale/position nodes
      */
     export class GizmoManager implements IDisposable {
         private scene;
@@ -53629,9 +53683,12 @@ declare module BABYLON {
         clearGizmoOnEmptyPointerEvent: boolean;
         /** Fires an event when the manager is attached to a mesh */
         onAttachedToMeshObservable: Observable<Nullable<AbstractMesh>>;
+        /** Fires an event when the manager is attached to a node */
+        onAttachedToNodeObservable: Observable<Nullable<Node>>;
         private _gizmosEnabled;
         private _pointerObserver;
         private _attachedMesh;
+        private _attachedNode;
         private _boundingBoxColor;
         private _defaultUtilityLayer;
         private _defaultKeepDepthUtilityLayer;
@@ -53645,7 +53702,11 @@ declare module BABYLON {
          */
         attachableMeshes: Nullable<Array<AbstractMesh>>;
         /**
-         * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh. (Default: true)
+         * Array of nodes which will have the gizmo attached when a pointer selected them. If null, all nodes are attachable. (Default: null)
+         */
+        attachableNodes: Nullable<Array<Node>>;
+        /**
+         * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh/attachToNode. (Default: true)
          */
         usePointerToAttachGizmos: boolean;
         /**
@@ -53668,6 +53729,11 @@ declare module BABYLON {
          */
         attachToMesh(mesh: Nullable<AbstractMesh>): void;
         /**
+         * Attaches a set of gizmos to the specified node
+         * @param node The node the gizmo's should be attached to
+         */
+        attachToNode(node: Nullable<Node>): void;
+        /**
          * If the position gizmo is enabled
          */
         set positionGizmoEnabled(value: boolean);
@@ -54037,6 +54103,47 @@ declare module BABYLON {
     }
 }
 declare module BABYLON {
+    /**
+     * Gizmo that enables viewing a camera
+     */
+    export class CameraGizmo extends Gizmo {
+        private _cameraMesh;
+        private _cameraLinesMesh;
+        private _material;
+        /**
+         * Creates a CameraGizmo
+         * @param gizmoLayer The utility layer the gizmo will be added to
+         */
+        constructor(gizmoLayer?: UtilityLayerRenderer);
+        private _camera;
+        /** Gets or sets a boolean indicating if frustum lines must be rendered (true by default)) */
+        get displayFrustum(): boolean;
+        set displayFrustum(value: boolean);
+        /**
+         * The camera that the gizmo is attached to
+         */
+        set camera(camera: Nullable<Camera>);
+        get camera(): Nullable<Camera>;
+        /**
+         * Gets the material used to render the camera gizmo
+         */
+        get material(): StandardMaterial;
+        /**
+         * @hidden
+         * Updates the gizmo to match the attached mesh's position/rotation
+         */
+        protected _update(): void;
+        private static _Scale;
+        private _invProjection;
+        /**
+         * Disposes of the camera gizmo
+         */
+        dispose(): void;
+        private static _CreateCameraMesh;
+        private static _CreateCameraFrustum;
+    }
+}
+declare module BABYLON {
     /** @hidden */
     export var backgroundFragmentDeclaration: {
         name: string;
@@ -68631,6 +68738,11 @@ declare module BABYLON {
          */
         degree: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "BlackAndWhitePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a black and white post process
          * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#black-and-white
          * @param name The name of the effect.
@@ -68641,6 +68753,8 @@ declare module BABYLON {
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<BlackAndWhitePostProcess>;
     }
 }
 declare module BABYLON {
@@ -68757,6 +68871,11 @@ declare module BABYLON {
          * @hidden
          */
         _inputPostProcess: Nullable<PostProcess>;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "ExtractHighlightsPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
     }
 }
@@ -68775,6 +68894,11 @@ declare module BABYLON {
         /** Weight of the bloom to be added to the original input. */
         weight: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "BloomMergePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of @see BloomMergePostProcess
          * @param name The name of the effect.
          * @param originalFromInput Post process which's input will be used for the merge.
@@ -68880,6 +69004,15 @@ declare module BABYLON {
          * The center position where the radialIntensity should be around. [0.5,0.5 is center of screen, 1,1 is top right corder] (default: Vector2(0.5 ,0.5))
          */
         centerPosition: Vector2;
+        /** The width of the screen to apply the effect on */
+        screenWidth: number;
+        /** The height of the screen to apply the effect on */
+        screenHeight: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "ChromaticAberrationPostProcess" string
+         */
+        getClassName(): string;
         /**
          * Creates a new instance ChromaticAberrationPostProcess
          * @param name The name of the effect.
@@ -68894,6 +69027,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, screenWidth: number, screenHeight: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ChromaticAberrationPostProcess>;
     }
 }
 declare module BABYLON {
@@ -68924,6 +69059,11 @@ declare module BABYLON {
          * Focal length of the effect's camera in scene units/1000 (eg. millimeter). (default: 50)
          */
         focalLength: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "CircleOfConfusionPostProcess" string
+         */
+        getClassName(): string;
         private _depthTexture;
         /**
          * Creates a new instance CircleOfConfusionPostProcess
@@ -68969,7 +69109,18 @@ declare module BABYLON {
      */
     export class ColorCorrectionPostProcess extends PostProcess {
         private _colorTableTexture;
+        /**
+         * Gets the color table url used to create the LUT texture
+         */
+        colorTableUrl: string;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "ColorCorrectionPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, colorTableUrl: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ColorCorrectionPostProcess>;
     }
 }
 declare module BABYLON {
@@ -68989,6 +69140,11 @@ declare module BABYLON {
         /** Array of 9 values corresponding to the 3x3 kernel to be applied */
         kernel: number[];
         /**
+         * Gets a string identifying the name of the class
+         * @returns "ConvolutionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance ConvolutionPostProcess
          * @param name The name of the effect.
          * @param kernel Array of 9 values corresponding to the 3x3 kernel to be applied
@@ -68999,9 +69155,9 @@ declare module BABYLON {
          * @param reusable If the post process can be reused on the same frame. (default: false)
          * @param textureType Type of textures used when performing the post process. (default: 0)
          */
-        constructor(name: string, 
-        /** Array of 9 values corresponding to the 3x3 kernel to be applied */
-        kernel: number[], options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
+        constructor(name: string, kernel: number[], options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ConvolutionPostProcess>;
         /**
          * Edge detection 0 see https://en.wikipedia.org/wiki/Kernel_(image_processing)
          */
@@ -69036,8 +69192,16 @@ declare module BABYLON {
      * See section 2.6.2 http://fileadmin.cs.lth.se/cs/education/edan35/lectures/12dof.pdf
      */
     export class DepthOfFieldBlurPostProcess extends BlurPostProcess {
+        /**
+         * The direction the blur should be applied
+         */
         direction: Vector2;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "DepthOfFieldBlurPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance CircleOfConfusionPostProcess
          * @param name The name of the effect.
          * @param scene The scene the effect belongs to.
@@ -69093,6 +69257,11 @@ declare module BABYLON {
     export class DepthOfFieldMergePostProcess extends PostProcess {
         private blurSteps;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "DepthOfFieldMergePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of DepthOfFieldMergePostProcess
          * @param name The name of the effect.
          * @param originalFromInput Post process which's input will be used for the merge.
@@ -69219,6 +69388,11 @@ declare module BABYLON {
      */
     export class DisplayPassPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "DisplayPassPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates the DisplayPassPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -69228,6 +69402,8 @@ declare module BABYLON {
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<DisplayPassPostProcess>;
     }
 }
 declare module BABYLON {
@@ -69245,6 +69421,11 @@ declare module BABYLON {
         /** The matrix to be applied to the image */
         kernelMatrix: Matrix;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "FilterPostProcess" string
+         */
+        getClassName(): string;
+        /**
          *
          * @param name The name of the effect.
          * @param kernelMatrix The matrix to be applied to the image
@@ -69254,9 +69435,9 @@ declare module BABYLON {
          * @param engine The engine which the post process will be applied. (default: current engine)
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
-        constructor(name: string, 
-        /** The matrix to be applied to the image */
-        kernelMatrix: Matrix, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        constructor(name: string, kernelMatrix: Matrix, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<FilterPostProcess>;
     }
 }
 declare module BABYLON {
@@ -69279,12 +69460,15 @@ declare module BABYLON {
      * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#fxaa
      */
     export class FxaaPostProcess extends PostProcess {
-        /** @hidden */
-        texelWidth: number;
-        /** @hidden */
-        texelHeight: number;
+        /**
+         * Gets a string identifying the name of the class
+         * @returns "FxaaPostProcess" string
+         */
+        getClassName(): string;
         constructor(name: string, options: number | PostProcessOptions, camera?: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number);
         private _getDefines;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): FxaaPostProcess;
     }
 }
 declare module BABYLON {
@@ -69308,6 +69492,11 @@ declare module BABYLON {
          */
         animated: boolean;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "GrainPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of @see GrainPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -69319,6 +69508,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): GrainPostProcess;
     }
 }
 declare module BABYLON {
@@ -69335,6 +69526,11 @@ declare module BABYLON {
      */
     export class HighlightsPostProcess extends PostProcess {
         /**
+         * Gets a string identifying the name of the class
+         * @returns "HighlightsPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Extracts highlights from the image
          * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses
          * @param name The name of the effect.
@@ -69602,6 +69798,11 @@ declare module BABYLON {
         private _motionBlurSamples;
         private _geometryBufferRenderer;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "MotionBlurPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance MotionBlurPostProcess
          * @param name The name of the effect.
          * @param scene The scene containing the objects to blur according to their velocity.
@@ -69631,6 +69832,8 @@ declare module BABYLON {
          * @param camera The camera to dispose the post process on.
          */
         dispose(camera?: Camera): void;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<MotionBlurPostProcess>;
     }
 }
 declare module BABYLON {
@@ -69646,14 +69849,16 @@ declare module BABYLON {
      * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#refraction
      */
     export class RefractionPostProcess extends PostProcess {
+        private _refTexture;
+        private _ownRefractionTexture;
         /** the base color of the refraction (used to taint the rendering) */
         color: Color3;
         /** simulated refraction depth */
         depth: number;
         /** the coefficient of the base color (0 to remove base color tainting) */
         colorLevel: number;
-        private _refTexture;
-        private _ownRefractionTexture;
+        /** Gets the url used to load the refraction texture */
+        refractionTextureUrl: string;
         /**
          * Gets or sets the refraction texture
          * Please note that you are responsible for disposing the texture if you set it manually
@@ -69661,6 +69866,11 @@ declare module BABYLON {
         get refractionTexture(): Texture;
         set refractionTexture(value: Texture);
         /**
+         * Gets a string identifying the name of the class
+         * @returns "RefractionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes the RefractionPostProcess
          * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#refraction
          * @param name The name of the effect.
@@ -69674,18 +69884,14 @@ declare module BABYLON {
          * @param engine The engine which the post process will be applied. (default: current engine)
          * @param reusable If the post process can be reused on the same frame. (default: false)
          */
-        constructor(name: string, refractionTextureUrl: string, 
-        /** the base color of the refraction (used to taint the rendering) */
-        color: Color3, 
-        /** simulated refraction depth */
-        depth: number, 
-        /** the coefficient of the base color (0 to remove base color tainting) */
-        colorLevel: number, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
+        constructor(name: string, refractionTextureUrl: string, color: Color3, depth: number, colorLevel: number, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean);
         /**
          * Disposes of the post process
          * @param camera Camera to dispose post process on
          */
         dispose(camera: Camera): void;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): RefractionPostProcess;
     }
 }
 declare module BABYLON {
@@ -69710,6 +69916,11 @@ declare module BABYLON {
          */
         edgeAmount: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "SharpenPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance ConvolutionPostProcess
          * @param name The name of the effect.
          * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -69721,6 +69932,8 @@ declare module BABYLON {
          * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
          */
         constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType?: number, blockCompilation?: boolean);
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): SharpenPostProcess;
     }
 }
 declare module BABYLON {
@@ -70678,6 +70891,11 @@ declare module BABYLON {
         private _reflectionSamples;
         private _smoothSteps;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "ScreenSpaceReflectionPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance of ScreenSpaceReflectionPostProcess.
          * @param name The name of the effect.
          * @param scene The scene containing the objects to calculate reflections.
@@ -70718,6 +70936,8 @@ declare module BABYLON {
         get smoothSteps(): number;
         set smoothSteps(steps: number);
         private _updateEffectDefines;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): ScreenSpaceReflectionPostProcess;
     }
 }
 declare module BABYLON {
@@ -71106,6 +71326,11 @@ declare module BABYLON {
         private _stepSize;
         private _passedProcess;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "StereoscopicInterlacePostProcessI" string
+         */
+        getClassName(): string;
+        /**
          * Initializes a StereoscopicInterlacePostProcessI
          * @param name The name of the effect.
          * @param rigCameras The rig cameras to be appled to the post process
@@ -71124,6 +71349,11 @@ declare module BABYLON {
         private _stepSize;
         private _passedProcess;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "StereoscopicInterlacePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Initializes a StereoscopicInterlacePostProcess
          * @param name The name of the effect.
          * @param rigCameras The rig cameras to be appled to the post process
@@ -71162,6 +71392,11 @@ declare module BABYLON {
         /** Defines the required exposure adjustement */
         exposureAdjustment: number;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "TonemapPostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new TonemapPostProcess
          * @param name defines the name of the postprocess
          * @param _operator defines the operator to use
@@ -71327,6 +71562,11 @@ declare module BABYLON {
         valley: number;
         private _geometryBufferRenderer;
         /**
+         * Gets a string identifying the name of the class
+         * @returns "ScreenSpaceCurvaturePostProcess" string
+         */
+        getClassName(): string;
+        /**
          * Creates a new instance ScreenSpaceCurvaturePostProcess
          * @param name The name of the effect.
          * @param scene The scene containing the objects to blur according to their velocity.
@@ -71343,6 +71583,8 @@ declare module BABYLON {
          * Support test.
          */
         static get IsSupported(): boolean;
+        /** @hidden */
+        static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): ScreenSpaceCurvaturePostProcess;
     }
 }
 declare module BABYLON {

+ 48 - 48
dist/preview release/gui/babylon.gui.js

@@ -7,7 +7,7 @@
 		exports["babylonjs-gui"] = factory(require("babylonjs"));
 	else
 		root["BABYLON"] = root["BABYLON"] || {}, root["BABYLON"]["GUI"] = factory(root["BABYLON"]);
-})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_perfCounter__) {
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Maths_math_vector__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -400,7 +400,7 @@ module.exports = g;
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTextureInstrumentation", function() { return AdvancedDynamicTextureInstrumentation; });
-/* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/perfCounter */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/perfCounter */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -543,7 +543,7 @@ var AdvancedDynamicTextureInstrumentation = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTexture", function() { return AdvancedDynamicTexture; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _controls_container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./controls/container */ "./2D/controls/container.ts");
 /* harmony import */ var _style__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./style */ "./2D/style.ts");
@@ -1515,7 +1515,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _textBlock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./textBlock */ "./2D/controls/textBlock.ts");
 /* harmony import */ var _image__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./image */ "./2D/controls/image.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__);
 
 
@@ -1747,7 +1747,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__["_TypeStore"].RegisteredTy
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Checkbox", function() { return Checkbox; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -1930,7 +1930,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ColorPicker", function() { return ColorPicker; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
@@ -3319,7 +3319,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -3734,7 +3734,7 @@ babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredTypes
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control", function() { return Control; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -5680,7 +5680,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DisplayGrid", function() { return DisplayGrid; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -5913,7 +5913,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__);
 
 
@@ -6010,7 +6010,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__);
 
 
@@ -6468,7 +6468,7 @@ babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__["_TypeStore"].RegisteredTypes[
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Image", function() { return Image; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 
@@ -7403,7 +7403,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputPassword", function() { return InputPassword; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -7442,7 +7442,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__["_TypeStore"].RegisteredTy
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputText", function() { return InputText; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -8455,7 +8455,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Line", function() { return Line; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -8726,7 +8726,7 @@ babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].Registere
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLine", function() { return MultiLine; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _multiLinePoint__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../multiLinePoint */ "./2D/multiLinePoint.ts");
@@ -8996,7 +8996,7 @@ babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].Registe
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RadioButton", function() { return RadioButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -9203,7 +9203,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Rectangle", function() { return Rectangle; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -9353,7 +9353,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _scrollViewerWindow__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./scrollViewerWindow */ "./2D/controls/scrollViewers/scrollViewerWindow.ts");
 /* harmony import */ var _sliders_scrollBar__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../sliders/scrollBar */ "./2D/controls/sliders/scrollBar.ts");
 /* harmony import */ var _sliders_imageScrollBar__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../sliders/imageScrollBar */ "./2D/controls/sliders/imageScrollBar.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__);
 
 
@@ -10976,7 +10976,7 @@ var SelectionPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseSlider", function() { return BaseSlider; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -11306,7 +11306,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _baseSlider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./baseSlider */ "./2D/controls/sliders/baseSlider.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../measure */ "./2D/measure.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__);
 
 
@@ -11899,7 +11899,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Slider", function() { return Slider; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _baseSlider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./baseSlider */ "./2D/controls/sliders/baseSlider.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -12154,7 +12154,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__["_TypeStore"].RegisteredTy
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel", function() { return StackPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -12422,7 +12422,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextWrapping", function() { return TextWrapping; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextBlock", function() { return TextBlock; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -12885,7 +12885,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyPropertySet", function() { return KeyPropertySet; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualKeyboard", function() { return VirtualKeyboard; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./button */ "./2D/controls/button.ts");
@@ -13274,7 +13274,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector2WithInfo", function() { return Vector2WithInfo; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Matrix2D", function() { return Matrix2D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -13499,7 +13499,7 @@ var Matrix2D = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Measure", function() { return Measure; });
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__);
 
 var tmpRect = [
@@ -13648,7 +13648,7 @@ var Measure = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLinePoint", function() { return MultiLinePoint; });
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -13791,7 +13791,7 @@ var MultiLinePoint = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Style", function() { return Style; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -14097,7 +14097,7 @@ var ValueAndUnit = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "XmlLoader", function() { return XmlLoader; });
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -14416,7 +14416,7 @@ var XmlLoader = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbstractButton3D", function() { return AbstractButton3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
@@ -14459,7 +14459,7 @@ var AbstractButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Button3D", function() { return Button3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _abstractButton3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./abstractButton3D */ "./3D/controls/abstractButton3D.ts");
 /* harmony import */ var _2D_advancedDynamicTexture__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../2D/advancedDynamicTexture */ "./2D/advancedDynamicTexture.ts");
@@ -14640,7 +14640,7 @@ var Button3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container3D", function() { return Container3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
@@ -14797,7 +14797,7 @@ var Container3D = /** @class */ (function (_super) {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control3D", function() { return Control3D; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../vector3WithInfo */ "./3D/vector3WithInfo.ts");
 
@@ -15203,7 +15203,7 @@ var Control3D = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CylinderPanel", function() { return CylinderPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -15289,7 +15289,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HolographicButton", function() { return HolographicButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _button3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./button3D */ "./3D/controls/button3D.ts");
-/* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__);
 /* harmony import */ var _materials_fluentMaterial__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../materials/fluentMaterial */ "./3D/materials/fluentMaterial.ts");
 /* harmony import */ var _2D_controls_stackPanel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../2D/controls/stackPanel */ "./2D/controls/stackPanel.ts");
@@ -15783,7 +15783,7 @@ var MeshButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlanePanel", function() { return PlanePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
@@ -15838,7 +15838,7 @@ var PlanePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScatterPanel", function() { return ScatterPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -15965,7 +15965,7 @@ var ScatterPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SpherePanel", function() { return SpherePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -16051,7 +16051,7 @@ var SpherePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel3D", function() { return StackPanel3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
@@ -16176,7 +16176,7 @@ var StackPanel3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VolumeBasedPanel", function() { return VolumeBasedPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
@@ -16367,7 +16367,7 @@ var VolumeBasedPanel = /** @class */ (function (_super) {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GUI3DManager", function() { return GUI3DManager; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _controls_container3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./controls/container3D */ "./3D/controls/container3D.ts");
 
@@ -16634,7 +16634,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterialDefines", function() { return FluentMaterialDefines; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterial", function() { return FluentMaterial; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _shaders_fluent_vertex__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/fluent.vertex */ "./3D/materials/shaders/fluent.vertex.ts");
 /* harmony import */ var _shaders_fluent_fragment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shaders/fluent.fragment */ "./3D/materials/shaders/fluent.fragment.ts");
@@ -16957,7 +16957,7 @@ __webpack_require__.r(__webpack_exports__);
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentPixelShader", function() { return fluentPixelShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 var name = 'fluentPixelShader';
@@ -16979,7 +16979,7 @@ var fluentPixelShader = { name: name, shader: shader };
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentVertexShader", function() { return fluentVertexShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 var name = 'fluentVertexShader';
@@ -17002,7 +17002,7 @@ var fluentVertexShader = { name: name, shader: shader };
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector3WithInfo", function() { return Vector3WithInfo; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -17304,14 +17304,14 @@ if (typeof globalObject !== "undefined") {
 
 /***/ }),
 
-/***/ "babylonjs/Misc/perfCounter":
+/***/ "babylonjs/Maths/math.vector":
 /*!****************************************************************************************************!*\
   !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
   \****************************************************************************************************/
 /*! no static exports found */
 /***/ (function(module, exports) {
 
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_perfCounter__;
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Maths_math_vector__;
 
 /***/ })
 

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
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


File diff suppressed because it is too large
+ 137 - 36
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


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

@@ -59,6 +59,8 @@ declare module INSPECTOR {
         prepareGLTFPlugin(loader: BABYLON.GLTFFileLoader): void;
         lightGizmos: Array<BABYLON.LightGizmo>;
         enableLightGizmo(light: BABYLON.Light, enable?: boolean): void;
+        cameraGizmos: Array<BABYLON.CameraGizmo>;
+        enableCameraGizmo(camera: BABYLON.Camera, enable?: boolean): void;
     }
 }
 declare module INSPECTOR {
@@ -2915,15 +2917,18 @@ declare module INSPECTOR {
         camera: BABYLON.Camera;
         extensibilityGroups?: BABYLON.IExplorerExtensibilityGroup[];
         onClick: () => void;
+        globalState: GlobalState;
     }
     export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComponentProps, {
         isActive: boolean;
+        isGizmoEnabled: boolean;
     }> {
         private _onBeforeRenderObserver;
         constructor(props: ICameraTreeItemComponentProps);
         setActive(): void;
         componentDidMount(): void;
         componentWillUnmount(): void;
+        toggleGizmo(): void;
         render(): JSX.Element;
     }
 }

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

@@ -28,7 +28,9 @@ declare module "babylonjs-inspector/components/globalState" {
     import { ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
     import { Light } from "babylonjs/Lights/light";
+    import { Camera } from "babylonjs/Cameras/camera";
     import { LightGizmo } from "babylonjs/Gizmos/lightGizmo";
+    import { CameraGizmo } from "babylonjs/Gizmos/cameraGizmo";
     import { PropertyChangedEvent } from "babylonjs-inspector/components/propertyChangedEvent";
     import { ReplayRecorder } from "babylonjs-inspector/components/replayRecorder";
     export class GlobalState {
@@ -70,6 +72,8 @@ declare module "babylonjs-inspector/components/globalState" {
         prepareGLTFPlugin(loader: GLTFFileLoader): void;
         lightGizmos: Array<LightGizmo>;
         enableLightGizmo(light: Light, enable?: boolean): void;
+        cameraGizmos: Array<CameraGizmo>;
+        enableCameraGizmo(camera: Camera, enable?: boolean): void;
     }
 }
 declare module "babylonjs-inspector/components/actionTabs/paneComponent" {
@@ -3547,19 +3551,23 @@ declare module "babylonjs-inspector/components/sceneExplorer/entities/cameraTree
     import { IExplorerExtensibilityGroup } from "babylonjs/Debug/debugLayer";
     import { Camera } from "babylonjs/Cameras/camera";
     import * as React from "react";
+    import { GlobalState } from "babylonjs-inspector/components/globalState";
     interface ICameraTreeItemComponentProps {
         camera: Camera;
         extensibilityGroups?: IExplorerExtensibilityGroup[];
         onClick: () => void;
+        globalState: GlobalState;
     }
     export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComponentProps, {
         isActive: boolean;
+        isGizmoEnabled: boolean;
     }> {
         private _onBeforeRenderObserver;
         constructor(props: ICameraTreeItemComponentProps);
         setActive(): void;
         componentDidMount(): void;
         componentWillUnmount(): void;
+        toggleGizmo(): void;
         render(): JSX.Element;
     }
 }
@@ -4136,6 +4144,8 @@ declare module INSPECTOR {
         prepareGLTFPlugin(loader: BABYLON.GLTFFileLoader): void;
         lightGizmos: Array<BABYLON.LightGizmo>;
         enableLightGizmo(light: BABYLON.Light, enable?: boolean): void;
+        cameraGizmos: Array<BABYLON.CameraGizmo>;
+        enableCameraGizmo(camera: BABYLON.Camera, enable?: boolean): void;
     }
 }
 declare module INSPECTOR {
@@ -6992,15 +7002,18 @@ declare module INSPECTOR {
         camera: BABYLON.Camera;
         extensibilityGroups?: BABYLON.IExplorerExtensibilityGroup[];
         onClick: () => void;
+        globalState: GlobalState;
     }
     export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComponentProps, {
         isActive: boolean;
+        isGizmoEnabled: boolean;
     }> {
         private _onBeforeRenderObserver;
         constructor(props: ICameraTreeItemComponentProps);
         setActive(): void;
         componentDidMount(): void;
         componentWillUnmount(): void;
+        toggleGizmo(): void;
         render(): JSX.Element;
     }
 }

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

@@ -1 +1 @@
-{"thinEngineOnly":117135,"engineOnly":153571,"sceneOnly":517676,"minGridMaterial":656009,"minStandardMaterial":805434}
+{"thinEngineOnly":117135,"engineOnly":153571,"sceneOnly":517838,"minGridMaterial":656171,"minStandardMaterial":805596}

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


File diff suppressed because it is too large
+ 103 - 99
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


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

@@ -17,9 +17,11 @@
 
 ### General
 
-- Added support for querystrings on KTX file URLs ([abogartz](https://github.com/abogartz/Babylon.js)
+- Added support for postproces serialization ([Deltakosh](https://github.com/deltakosh))
+- Added support for querystrings on KTX file URLs ([abogartz](https://github.com/abogartz)
 - Refactored React refs from old string API to React.createRef() API ([belfortk](https://github.com/belfortk))
 - Scale on one axis for `BoundingBoxGizmo` ([cedricguillemet](https://github.com/cedricguillemet))
+- Camera gizmo ([cedricguillemet](https://github.com/cedricguillemet))
 - Node support (Transform, Bone) for gizmos ([cedricguillemet](https://github.com/cedricguillemet))
 - Simplified code contributions by fully automating the dev setup with gitpod ([nisarhassan12](https://github.com/nisarhassan12))
 - Add a `CascadedShadowMap.IsSupported` method and log an error instead of throwing an exception when CSM is not supported ([Popov72](https://github.com/Popov72))
@@ -277,6 +279,7 @@
 - Fix an issue causing views to render blank when scene rendering is skipped for a given iteration of the render loop ([elInfidel](https://github.com/elInfidel))
 - Fix docs Matrix.RotationYawPitchRoll and Matrix.RotationYawPitchRollToRef ([VSerain](https://github.com/VSerain))
 - Fix issue in `GLTFLoader._updateBoneMatrices()` where bone rest position was not set. ([drigax](https://github.com/drigax))
+- Fix the bounding box of instances that does not match the instance position / rotation / scaling ([Popov72](https://github.com/Popov72))
 
 ## Breaking changes
 - `FollowCamera.target` was renamed to `FollowCamera.meshTarget` to not be in conflict with `TargetCamera.target` ([Deltakosh](https://github.com/deltakosh))

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

@@ -6,7 +6,9 @@ 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 { Camera } from "babylonjs/Cameras/camera";
 import { LightGizmo } from "babylonjs/Gizmos/lightGizmo";
+import { CameraGizmo } from "babylonjs/Gizmos/cameraGizmo";
 import { PropertyChangedEvent } from "./propertyChangedEvent";
 import { ReplayRecorder } from './replayRecorder';
 import { DataStorage } from 'babylonjs/Misc/dataStorage';
@@ -130,4 +132,23 @@ export class GlobalState {
             light.reservedDataStore.lightGizmo = null;
         }
     }
+    // Camera gizmos
+    public cameraGizmos: Array<CameraGizmo> = [];
+    public enableCameraGizmo(camera: Camera, enable = true) {
+        if (enable) {
+            if (!camera.reservedDataStore) {
+                camera.reservedDataStore = {}
+            }
+            if (!camera.reservedDataStore.cameraGizmo) {
+                camera.reservedDataStore.cameraGizmo = new CameraGizmo();
+                this.cameraGizmos.push(camera.reservedDataStore.cameraGizmo)
+                camera.reservedDataStore.cameraGizmo.camera = camera;
+                camera.reservedDataStore.cameraGizmo.material.reservedDataStore = {hidden: true};
+            }
+        } else if (camera.reservedDataStore && camera.reservedDataStore.cameraGizmo) {
+            this.cameraGizmos.splice(this.cameraGizmos.indexOf(camera.reservedDataStore.cameraGizmo), 1);
+            camera.reservedDataStore.cameraGizmo.dispose();
+            camera.reservedDataStore.cameraGizmo = null;
+        }
+    }
 }

+ 24 - 5
inspector/src/components/sceneExplorer/entities/cameraTreeItemComponent.tsx

@@ -5,18 +5,20 @@ import { Camera } from "babylonjs/Cameras/camera";
 import { Scene } from "babylonjs/scene";
 
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faVideo, faCamera } from '@fortawesome/free-solid-svg-icons';
+import { faVideo, faCamera, faEye } from '@fortawesome/free-solid-svg-icons';
 import { TreeItemLabelComponent } from "../treeItemLabelComponent";
 import { ExtensionsComponent } from "../extensionsComponent";
 import * as React from "react";
+import { GlobalState } from "../../globalState";
 
 interface ICameraTreeItemComponentProps {
     camera: Camera,
     extensibilityGroups?: IExplorerExtensibilityGroup[],
-    onClick: () => void
+    onClick: () => void,
+    globalState: GlobalState
 }
 
-export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComponentProps, { isActive: boolean }> {
+export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComponentProps, { isActive: boolean, isGizmoEnabled:boolean }> {
     private _onBeforeRenderObserver: Nullable<Observer<Scene>>;
 
     constructor(props: ICameraTreeItemComponentProps) {
@@ -25,7 +27,7 @@ export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComp
         const camera = this.props.camera;
         const scene = camera.getScene();
 
-        this.state = { isActive: scene.activeCamera === camera };
+        this.state = { isActive: scene.activeCamera === camera, isGizmoEnabled: (camera.reservedDataStore && camera.reservedDataStore.cameraGizmo) };
     }
 
     setActive(): void {
@@ -65,10 +67,24 @@ export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComp
         }
     }
 
+    toggleGizmo(): void {
+        const camera = this.props.camera;
+        if(camera.reservedDataStore && camera.reservedDataStore.cameraGizmo){
+            if (camera.getScene().reservedDataStore && camera.getScene().reservedDataStore.gizmoManager) {
+                camera.getScene().reservedDataStore.gizmoManager.attachToMesh(null);
+            }
+            this.props.globalState.enableCameraGizmo(camera, false);
+            this.setState({ isGizmoEnabled: false });
+        }else{
+            this.props.globalState.enableCameraGizmo(camera, true);
+            this.setState({ isGizmoEnabled: true });
+        }
+    }
+
     render() {
         const isActiveElement = this.state.isActive ? <FontAwesomeIcon icon={faVideo} /> : <FontAwesomeIcon icon={faVideo} className="isNotActive" />;
         const scene = this.props.camera.getScene()!;
-
+        const isGizmoEnabled = (this.state.isGizmoEnabled || (this.props.camera && this.props.camera.reservedDataStore && this.props.camera.reservedDataStore.cameraGizmo)) ? <FontAwesomeIcon icon={faEye} /> : <FontAwesomeIcon icon={faEye} className="isNotActive" />;
         return (
             <div className="cameraTools">
                 <TreeItemLabelComponent label={this.props.camera.name} onClick={() => this.props.onClick()} icon={faCamera} color="green" />
@@ -78,6 +94,9 @@ export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComp
                         {isActiveElement}
                     </div>
                 }
+                <div className="enableGizmo icon" onClick={() => this.toggleGizmo()} title="Turn on/off the camera's gizmo">
+                    {isGizmoEnabled}
+                </div>
                 <ExtensionsComponent target={this.props.camera} extensibilityGroups={this.props.extensibilityGroups} />
             </div>
         )

+ 78 - 23
inspector/src/components/sceneExplorer/entities/sceneTreeItemComponent.tsx

@@ -14,6 +14,7 @@ import { GlobalState } from "../../globalState";
 import { UtilityLayerRenderer } from "babylonjs/Rendering/utilityLayerRenderer";
 import { PropertyChangedEvent } from '../../../components/propertyChangedEvent';
 import { LightGizmo } from 'babylonjs/Gizmos/lightGizmo';
+import { CameraGizmo } from 'babylonjs/Gizmos/cameraGizmo';
 import { TmpVectors, Vector3 } from 'babylonjs/Maths/math';
 
 interface ISceneTreeItemComponentProps {
@@ -89,11 +90,17 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                         this.props.globalState.enableLightGizmo(this._selectedEntity, true);
                         this.forceUpdate();
                     }
-                    manager.attachToMesh(this._selectedEntity.reservedDataStore.lightGizmo.attachedMesh);
+                    manager.attachToNode(this._selectedEntity.reservedDataStore.lightGizmo.attachedNode);
+                } else if (className.indexOf("Camera") !== -1) {
+                    if (!this._selectedEntity.reservedDataStore || !this._selectedEntity.reservedDataStore.cameraGizmo) {
+                        this.props.globalState.enableCameraGizmo(this._selectedEntity, true);
+                        this.forceUpdate();
+                    }
+                    manager.attachToNode(this._selectedEntity.reservedDataStore.cameraGizmo.attachedNode);
                 }else if(className.indexOf("Bone") !== -1){
                     manager.attachToMesh((this._selectedEntity._linkedTransformNode)?this._selectedEntity._linkedTransformNode:this._selectedEntity);
                 } else {
-                    manager.attachToMesh(null);
+                    manager.attachToNode(null);
                 }
             }
         });
@@ -160,7 +167,23 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                     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) {
+                            if (g.attachedNode == m) {
+                                return true;
+                            }
+                        }
+                        return false;
+                    });
+                    if (pickInfo && pickInfo.hit && this.props.onSelectionChangedObservable) {
+                        this.props.onSelectionChangedObservable.notifyObservers(pickInfo.pickedMesh);
+                        return;
+                    }
+                }
+                // Pick camera gizmos
+                if (this.props.globalState.cameraGizmos.length > 0) {
+                    var gizmoScene = this.props.globalState.cameraGizmos[0].gizmoLayer.utilityLayerScene;
+                    let pickInfo = gizmoScene.pick(pickPosition.x, pickPosition.y, (m: any) => {
+                        for (var g of (this.props.globalState.cameraGizmos as any)) {
+                            if (g.attachedNode == m) {
                                 return true;
                             }
                         }
@@ -209,7 +232,7 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                     }
                     for (var gizmo of this.props.globalState.lightGizmos) {
                         if (gizmo._rootMesh == node) {
-                            manager.attachToMesh(gizmo.attachedMesh);
+                            manager.attachToNode(gizmo.attachedNode);
                         }
                     }
                 }
@@ -232,16 +255,28 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                     if (!this._posDragEnd) {
                         // Record movement for generating replay code
                         this._posDragEnd = manager.gizmos.positionGizmo!.onDragEndObservable.add(() => {
-                            if (manager.gizmos.positionGizmo && manager.gizmos.positionGizmo.attachedMesh) {
-                                var lightGizmo: Nullable<LightGizmo> = manager.gizmos.positionGizmo.attachedMesh.reservedDataStore ? manager.gizmos.positionGizmo.attachedMesh.reservedDataStore.lightGizmo : null;
-                                var obj: any = (lightGizmo && lightGizmo.light) ? lightGizmo.light : manager.gizmos.positionGizmo.attachedMesh;
+                            if (manager.gizmos.positionGizmo && manager.gizmos.positionGizmo.attachedNode) {
+                                var lightGizmo: Nullable<LightGizmo> = manager.gizmos.positionGizmo.attachedNode.reservedDataStore ? manager.gizmos.positionGizmo.attachedNode.reservedDataStore.lightGizmo : null;
+                                var objLight: any = (lightGizmo && lightGizmo.light) ? lightGizmo.light : manager.gizmos.positionGizmo.attachedNode;
 
-                                if (obj.position) {
+                                if (objLight.position) {
                                     var e = new PropertyChangedEvent();
-                                    e.object = obj
+                                    e.object = objLight
                                     e.property = "position"
-                                    e.value = obj.position;
+                                    e.value = objLight.position;
                                     this.props.globalState.onPropertyChangedObservable.notifyObservers(e)
+                                } else {
+                                    var cameraGizmo: Nullable<CameraGizmo> = manager.gizmos.positionGizmo.attachedNode.reservedDataStore ? manager.gizmos.positionGizmo.attachedNode.reservedDataStore.cameraGizmo : null;
+                                    var objCamera: any = (cameraGizmo && cameraGizmo.camera) ? cameraGizmo.camera : manager.gizmos.positionGizmo.attachedNode;
+    
+                                    if (objCamera.position) {
+                                        var e = new PropertyChangedEvent();
+                                        e.object = objCamera
+                                        e.property = "position"
+                                        e.value = objCamera.position;
+                                        this.props.globalState.onPropertyChangedObservable.notifyObservers(e)
+                                    }
+
                                 }
                             }
                         })
@@ -253,27 +288,41 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                     if (!this._rotateDragEnd) {
                         // Record movement for generating replay code
                         this._rotateDragEnd = manager.gizmos.rotationGizmo!.onDragEndObservable.add(() => {
-                            if (manager.gizmos.rotationGizmo && manager.gizmos.rotationGizmo.attachedMesh) {
-                                var lightGizmo: Nullable<LightGizmo> = manager.gizmos.rotationGizmo.attachedMesh.reservedDataStore ? manager.gizmos.rotationGizmo.attachedMesh.reservedDataStore.lightGizmo : null;
-                                var obj: any = (lightGizmo && lightGizmo.light) ? lightGizmo.light : manager.gizmos.rotationGizmo.attachedMesh;
+                            if (manager.gizmos.rotationGizmo && manager.gizmos.rotationGizmo.attachedNode) {
+                                var lightGizmo: Nullable<LightGizmo> = manager.gizmos.rotationGizmo.attachedNode.reservedDataStore ? manager.gizmos.rotationGizmo.attachedNode.reservedDataStore.lightGizmo : null;
+                                var objLight: any = (lightGizmo && lightGizmo.light) ? lightGizmo.light : manager.gizmos.rotationGizmo.attachedNode;
+                                var cameraGizmo: Nullable<CameraGizmo> = manager.gizmos.rotationGizmo.attachedNode.reservedDataStore ? manager.gizmos.rotationGizmo.attachedNode.reservedDataStore.cameraGizmo : null;
+                                var objCamera: any = (cameraGizmo && cameraGizmo.camera) ? cameraGizmo.camera : manager.gizmos.rotationGizmo.attachedNode;
 
-                                if (obj.rotationQuaternion) {
+                                if (objLight.rotationQuaternion) {
                                     var e = new PropertyChangedEvent();
-                                    e.object = obj;
+                                    e.object = objLight;
                                     e.property = "rotationQuaternion";
-                                    e.value = obj.rotationQuaternion;
+                                    e.value = objLight.rotationQuaternion;
                                     this.props.globalState.onPropertyChangedObservable.notifyObservers(e);
-                                } else if (obj.rotation) {
+                                } else if (objLight.rotation) {
                                     var e = new PropertyChangedEvent();
-                                    e.object = obj;
+                                    e.object = objLight;
                                     e.property = "rotation";
-                                    e.value = obj.rotation;
+                                    e.value = objLight.rotation;
                                     this.props.globalState.onPropertyChangedObservable.notifyObservers(e);
-                                } else if (obj.direction) {
+                                } else if (objLight.direction) {
                                     var e = new PropertyChangedEvent();
-                                    e.object = obj;
+                                    e.object = objLight;
                                     e.property = "direction";
-                                    e.value = obj.direction;
+                                    e.value = objLight.direction;
+                                    this.props.globalState.onPropertyChangedObservable.notifyObservers(e);
+                                } else if (objCamera.rotationQuaternion) {
+                                    var e = new PropertyChangedEvent();
+                                    e.object = objCamera;
+                                    e.property = "rotationQuaternion";
+                                    e.value = objCamera.rotationQuaternion;
+                                    this.props.globalState.onPropertyChangedObservable.notifyObservers(e);
+                                } else if (objCamera.rotation) {
+                                    var e = new PropertyChangedEvent();
+                                    e.object = objCamera;
+                                    e.property = "rotation";
+                                    e.value = objCamera.rotation;
                                     this.props.globalState.onPropertyChangedObservable.notifyObservers(e);
                                 }
                             }
@@ -320,7 +369,13 @@ export class SceneTreeItemComponent extends React.Component<ISceneTreeItemCompon
                         this.props.globalState.enableLightGizmo(this._selectedEntity, true);
                         this.forceUpdate();
                     }
-                    manager.attachToMesh(this._selectedEntity.reservedDataStore.lightGizmo.attachedMesh);
+                    manager.attachToNode(this._selectedEntity.reservedDataStore.lightGizmo.attachedNode);
+                } else if (className.indexOf("Camera") !== -1) {
+                    if (!this._selectedEntity.reservedDataStore || !this._selectedEntity.reservedDataStore.cameraGizmo) {
+                        this.props.globalState.enableCameraGizmo(this._selectedEntity, true);
+                        this.forceUpdate();
+                    }
+                    manager.attachToNode(this._selectedEntity.reservedDataStore.cameraGizmo.attachedNode);
                 } else if(className.indexOf("Bone") !== -1){
                     manager.attachToMesh((this._selectedEntity._linkedTransformNode)?this._selectedEntity._linkedTransformNode:this._selectedEntity);
                 }

+ 6 - 2
inspector/src/components/sceneExplorer/sceneExplorer.scss

@@ -402,16 +402,20 @@
         .cameraTools {
             grid-column: 2;
             display: grid;
-            grid-template-columns: 1fr 20px auto 5px;
+            grid-template-columns: 1fr 20px 20px auto 5px;
             align-items: center;
 
             .activeCamera {
                 grid-column: 2;
             }
 
+            .enableGizmo {
+                grid-column: 3;          
+            } 
+
             .extensions {
                 width: 20px;
-                grid-column: 3;
+                grid-column: 4;
             }
         }
 

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

@@ -96,7 +96,7 @@ export class TreeItemSpecializedComponent extends React.Component<ITreeItemSpeci
             }
 
             if (className.indexOf("Camera") !== -1) {
-                return (<CameraTreeItemComponent extensibilityGroups={this.props.extensibilityGroups} camera={entity as Camera} onClick={() => this.onClick()} />);
+                return (<CameraTreeItemComponent globalState={this.props.globalState} extensibilityGroups={this.props.extensibilityGroups} camera={entity as Camera} onClick={() => this.onClick()} />);
             }
 
             if (className.indexOf("Light", className.length - 5) !== -1) {

+ 5 - 0
inspector/src/inspector.ts

@@ -492,6 +492,11 @@ export class Inspector {
                 this._GlobalState.enableLightGizmo(g.light, false);
             }
         });
+        this._GlobalState.cameraGizmos.forEach((g) => {
+            if (g.camera) {
+                this._GlobalState.enableCameraGizmo(g.camera, false);
+            }
+        });
         if (this._Scene && this._Scene.reservedDataStore && this._Scene.reservedDataStore.gizmoManager) {
             this._Scene.reservedDataStore.gizmoManager.dispose();
             this._Scene.reservedDataStore.gizmoManager = null;

+ 1 - 1
src/Engines/thinEngine.ts

@@ -941,7 +941,7 @@ export class ThinEngine {
     }
 
     /**
-     * Gets a string idenfifying the name of the class
+     * Gets a string identifying the name of the class
      * @returns "Engine" string
      */
     public getClassName(): string {

+ 190 - 0
src/Gizmos/cameraGizmo.ts

@@ -0,0 +1,190 @@
+import { Nullable } from "../types";
+import { Vector3 } from "../Maths/math.vector";
+import { Color3 } from '../Maths/math.color';
+import { Mesh } from "../Meshes/mesh";
+import { Gizmo } from "./gizmo";
+import { UtilityLayerRenderer } from "../Rendering/utilityLayerRenderer";
+import { StandardMaterial } from '../Materials/standardMaterial';
+import { Scene } from '../scene';
+import { Camera } from '../Cameras/camera';
+import { BoxBuilder } from "../Meshes/Builders/boxBuilder";
+import { CylinderBuilder } from '../Meshes/Builders/cylinderBuilder';
+import { Matrix } from '../Maths/math';
+import { LinesBuilder } from "../Meshes/Builders/linesBuilder";
+
+/**
+ * Gizmo that enables viewing a camera
+ */
+export class CameraGizmo extends Gizmo {
+    private _cameraMesh: Mesh;
+    private _cameraLinesMesh: Mesh;
+    private _material: StandardMaterial;
+
+    /**
+     * Creates a CameraGizmo
+     * @param gizmoLayer The utility layer the gizmo will be added to
+     */
+    constructor(gizmoLayer?: UtilityLayerRenderer) {
+        super(gizmoLayer);
+
+        this._material = new StandardMaterial("cameraGizmoMaterial", this.gizmoLayer.utilityLayerScene);
+        this._material.diffuseColor = new Color3(0.5, 0.5, 0.5);
+        this._material.specularColor = new Color3(0.1, 0.1, 0.1);
+    }
+    private _camera: Nullable<Camera> = null;
+
+    /** Gets or sets a boolean indicating if frustum lines must be rendered (true by default)) */
+    public get displayFrustum() {
+        return this._cameraLinesMesh.isEnabled();
+    }
+    public set displayFrustum(value) {
+        this._cameraLinesMesh.setEnabled(value);
+    }
+
+    /**
+     * The camera that the gizmo is attached to
+     */
+    public set camera(camera: Nullable<Camera>) {
+        this._camera = camera;
+        this.attachedNode = camera;
+        if (camera) {
+            // Create the mesh for the given camera
+            if (this._cameraMesh) {
+                this._cameraMesh.dispose();
+            }
+            if (this._cameraLinesMesh) {
+                this._cameraLinesMesh.dispose();
+            }
+            this._cameraMesh = CameraGizmo._CreateCameraMesh(this.gizmoLayer.utilityLayerScene);
+            this._cameraLinesMesh = CameraGizmo._CreateCameraFrustum(this.gizmoLayer.utilityLayerScene);
+
+            this._cameraMesh.getChildMeshes(false).forEach((m) => {
+                m.material = this._material;
+            });
+            this._cameraMesh.parent = this._rootMesh;
+
+            this._cameraLinesMesh.parent = this._rootMesh;
+
+            if (this.gizmoLayer.utilityLayerScene.activeCamera && this.gizmoLayer.utilityLayerScene.activeCamera.maxZ < camera.maxZ * 1.5) {
+                this.gizmoLayer.utilityLayerScene.activeCamera.maxZ = camera.maxZ * 1.5;
+            }
+
+            if (!this.attachedNode!.reservedDataStore) {
+                this.attachedNode!.reservedDataStore = {};
+            }
+            this.attachedNode!.reservedDataStore.cameraGizmo = this;
+
+            // Add lighting to the camera gizmo
+            var gizmoLight = this.gizmoLayer._getSharedGizmoLight();
+            gizmoLight.includedOnlyMeshes = gizmoLight.includedOnlyMeshes.concat(this._cameraMesh.getChildMeshes(false));
+
+            this._update();
+        }
+    }
+
+    public get camera() {
+        return this._camera;
+    }
+
+    /**
+     * Gets the material used to render the camera gizmo
+     */
+    public get material() {
+        return this._material;
+    }
+    /**
+     * @hidden
+     * Updates the gizmo to match the attached mesh's position/rotation
+     */
+
+    protected _update() {
+        super._update();
+        if (!this._camera) {
+            return;
+        }
+
+        // frustum matrix
+        this._camera.getProjectionMatrix().invertToRef(this._invProjection);
+        this._cameraLinesMesh.setPivotMatrix(this._invProjection, false);
+
+        this._cameraLinesMesh.scaling.x = 1 / this._rootMesh.scaling.x;
+        this._cameraLinesMesh.scaling.y = 1 / this._rootMesh.scaling.y;
+        this._cameraLinesMesh.scaling.z = 1 / this._rootMesh.scaling.z;
+    }
+
+    // Static helper methods
+    private static _Scale = 0.05;
+    private _invProjection = new Matrix();
+
+    /**
+     * Disposes of the camera gizmo
+     */
+    public dispose() {
+        if (this._cameraMesh) {
+            this._cameraMesh.dispose();
+        }
+        if (this._cameraLinesMesh) {
+            this._cameraLinesMesh.dispose();
+        }
+        this._material.dispose();
+        super.dispose();
+    }
+
+    private static _CreateCameraMesh(scene: Scene) {
+        var root = new Mesh("rootCameraGizmo", scene);
+
+        var mesh = new Mesh(root.name, scene);
+        mesh.parent = root;
+
+        var box = BoxBuilder.CreateBox(root.name, {width: 1.0, height: 0.8, depth: 0.5 }, scene);
+        box.parent = mesh;
+
+        var cyl1 = CylinderBuilder.CreateCylinder(root.name, {height: 0.5, diameterTop: 0.8, diameterBottom: 0.8}, scene);
+        cyl1.parent = mesh;
+        cyl1.position.y = 0.3;
+        cyl1.position.x = -0.6;
+        cyl1.rotation.x = Math.PI * 0.5;
+
+        var cyl2 = CylinderBuilder.CreateCylinder(root.name, {height: 0.5, diameterTop: 0.6, diameterBottom: 0.6}, scene);
+        cyl2.parent = mesh;
+        cyl2.position.y = 0.5;
+        cyl2.position.x = 0.4;
+        cyl2.rotation.x = Math.PI * 0.5;
+
+        var cyl3 = CylinderBuilder.CreateCylinder(root.name, {height: 0.5, diameterTop: 0.5, diameterBottom: 0.5}, scene);
+        cyl3.parent = mesh;
+        cyl3.position.y = 0.0;
+        cyl3.position.x = 0.6;
+        cyl3.rotation.z = Math.PI * 0.5;
+
+        root.scaling.scaleInPlace(CameraGizmo._Scale);
+        root.rotation.y = -Math.PI * 0.5;
+        mesh.position.x = -0.9;
+
+        return root;
+    }
+
+    private static _CreateCameraFrustum(scene: Scene) {
+        var root = new Mesh("rootCameraGizmo", scene);
+        var mesh = new Mesh(root.name, scene);
+        mesh.parent = root;
+
+        for (var y = 0; y < 4; y += 2)
+        {
+            for (var x = 0; x < 4; x += 2)
+            {
+                var line = LinesBuilder.CreateLines("lines", { points: [new Vector3(-1 + x, -1 + y, -1), new Vector3(-1 + x, -1 + y, 1)] }, scene);
+                line.parent = mesh;
+                line.alwaysSelectAsActiveMesh = true;
+                var line = LinesBuilder.CreateLines("lines", { points: [new Vector3(-1, -1 + x, -1 + y), new Vector3(1, -1 + x, -1 + y)] }, scene);
+                line.parent = mesh;
+                line.alwaysSelectAsActiveMesh = true;
+                var line = LinesBuilder.CreateLines("lines", { points: [new Vector3(-1 + x, -1, -1 + y), new Vector3(-1 + x,  1, -1 + y)] }, scene);
+                line.parent = mesh;
+                line.alwaysSelectAsActiveMesh = true;
+            }
+        }
+
+        return root;
+    }
+}

+ 72 - 10
src/Gizmos/gizmoManager.ts

@@ -15,20 +15,27 @@ import { ScaleGizmo } from "./scaleGizmo";
 import { BoundingBoxGizmo } from "./boundingBoxGizmo";
 
 /**
- * Helps setup gizmo's in the scene to rotate/scale/position meshes
+ * Helps setup gizmo's in the scene to rotate/scale/position nodes
  */
 export class GizmoManager implements IDisposable {
     /**
      * Gizmo's created by the gizmo manager, gizmo will be null until gizmo has been enabled for the first time
      */
     public gizmos: { positionGizmo: Nullable<PositionGizmo>, rotationGizmo: Nullable<RotationGizmo>, scaleGizmo: Nullable<ScaleGizmo>, boundingBoxGizmo: Nullable<BoundingBoxGizmo> };
+
     /** When true, the gizmo will be detached from the current object when a pointer down occurs with an empty picked mesh */
     public clearGizmoOnEmptyPointerEvent = false;
+
     /** Fires an event when the manager is attached to a mesh */
     public onAttachedToMeshObservable = new Observable<Nullable<AbstractMesh>>();
+
+    /** Fires an event when the manager is attached to a node */
+    public onAttachedToNodeObservable = new Observable<Nullable<Node>>();
+
     private _gizmosEnabled = { positionGizmo: false, rotationGizmo: false, scaleGizmo: false, boundingBoxGizmo: false };
     private _pointerObserver: Nullable<Observer<PointerInfo>> = null;
     private _attachedMesh: Nullable<AbstractMesh> = null;
+    private _attachedNode: Nullable<Node> = null;
     private _boundingBoxColor = Color3.FromHexString("#0984e3");
     private _defaultUtilityLayer: UtilityLayerRenderer;
     private _defaultKeepDepthUtilityLayer: UtilityLayerRenderer;
@@ -42,7 +49,11 @@ export class GizmoManager implements IDisposable {
      */
     public attachableMeshes: Nullable<Array<AbstractMesh>> = null;
     /**
-     * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh. (Default: true)
+     * Array of nodes which will have the gizmo attached when a pointer selected them. If null, all nodes are attachable. (Default: null)
+     */
+    public attachableNodes: Nullable<Array<Node>> = null;
+    /**
+     * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh/attachToNode. (Default: true)
      */
     public usePointerToAttachGizmos = true;
 
@@ -124,7 +135,11 @@ export class GizmoManager implements IDisposable {
         if (this._attachedMesh) {
             this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
         }
+        if (this._attachedNode) {
+            this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
+        }
         this._attachedMesh = mesh;
+        this._attachedNode = null;
         for (var key in this.gizmos) {
             var gizmo = <Nullable<Gizmo>>((<any>this.gizmos)[key]);
             if (gizmo && (<any>this._gizmosEnabled)[key]) {
@@ -138,6 +153,31 @@ export class GizmoManager implements IDisposable {
     }
 
     /**
+     * Attaches a set of gizmos to the specified node
+     * @param node The node the gizmo's should be attached to
+     */
+    public attachToNode(node: Nullable<Node>) {
+        if (this._attachedMesh) {
+            this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
+        }
+        if (this._attachedNode) {
+            this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
+        }
+        this._attachedMesh = null;
+        this._attachedNode = node;
+        for (var key in this.gizmos) {
+            var gizmo = <Nullable<Gizmo>>((<any>this.gizmos)[key]);
+            if (gizmo && (<any>this._gizmosEnabled)[key]) {
+                gizmo.attachedNode = node;
+            }
+        }
+        if (this.boundingBoxGizmoEnabled && this._attachedNode) {
+            this._attachedNode.addBehavior(this.boundingBoxDragBehavior);
+        }
+        this.onAttachedToNodeObservable.notifyObservers(node);
+    }
+
+    /**
      * If the position gizmo is enabled
      */
     public set positionGizmoEnabled(value: boolean) {
@@ -145,9 +185,13 @@ export class GizmoManager implements IDisposable {
             if (!this.gizmos.positionGizmo) {
                 this.gizmos.positionGizmo = new PositionGizmo(this._defaultUtilityLayer, this._thickness);
             }
-            this.gizmos.positionGizmo.attachedMesh = this._attachedMesh;
+            if (this._attachedNode) {
+                this.gizmos.positionGizmo.attachedNode = this._attachedNode;
+            } else {
+                this.gizmos.positionGizmo.attachedMesh = this._attachedMesh;
+            }
         } else if (this.gizmos.positionGizmo) {
-            this.gizmos.positionGizmo.attachedMesh = null;
+            this.gizmos.positionGizmo.attachedNode = null;
         }
         this._gizmosEnabled.positionGizmo = value;
     }
@@ -162,9 +206,13 @@ export class GizmoManager implements IDisposable {
             if (!this.gizmos.rotationGizmo) {
                 this.gizmos.rotationGizmo = new RotationGizmo(this._defaultUtilityLayer, 32, false, this._thickness);
             }
-            this.gizmos.rotationGizmo.attachedMesh = this._attachedMesh;
+            if (this._attachedNode) {
+                this.gizmos.rotationGizmo.attachedNode = this._attachedNode;
+            } else {
+                this.gizmos.rotationGizmo.attachedMesh = this._attachedMesh;
+            }
         } else if (this.gizmos.rotationGizmo) {
-            this.gizmos.rotationGizmo.attachedMesh = null;
+            this.gizmos.rotationGizmo.attachedNode = null;
         }
         this._gizmosEnabled.rotationGizmo = value;
     }
@@ -177,9 +225,13 @@ export class GizmoManager implements IDisposable {
     public set scaleGizmoEnabled(value: boolean) {
         if (value) {
             this.gizmos.scaleGizmo = this.gizmos.scaleGizmo || new ScaleGizmo(this._defaultUtilityLayer, this._thickness);
-            this.gizmos.scaleGizmo.attachedMesh = this._attachedMesh;
+            if (this._attachedNode) {
+                this.gizmos.scaleGizmo.attachedNode = this._attachedNode;
+            } else {
+                this.gizmos.scaleGizmo.attachedMesh = this._attachedMesh;
+            }
         } else if (this.gizmos.scaleGizmo) {
-            this.gizmos.scaleGizmo.attachedMesh = null;
+            this.gizmos.scaleGizmo.attachedNode = null;
         }
         this._gizmosEnabled.scaleGizmo = value;
     }
@@ -192,16 +244,26 @@ export class GizmoManager implements IDisposable {
     public set boundingBoxGizmoEnabled(value: boolean) {
         if (value) {
             this.gizmos.boundingBoxGizmo = this.gizmos.boundingBoxGizmo || new BoundingBoxGizmo(this._boundingBoxColor, this._defaultKeepDepthUtilityLayer);
-            this.gizmos.boundingBoxGizmo.attachedMesh = this._attachedMesh;
+            if (this._attachedMesh) {
+                this.gizmos.boundingBoxGizmo.attachedMesh = this._attachedMesh;
+            } else {
+                this.gizmos.boundingBoxGizmo.attachedNode = this._attachedNode;
+            }
+
             if (this._attachedMesh) {
                 this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
                 this._attachedMesh.addBehavior(this.boundingBoxDragBehavior);
+            } else if (this._attachedNode) {
+                this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
+                this._attachedNode.addBehavior(this.boundingBoxDragBehavior);
             }
         } else if (this.gizmos.boundingBoxGizmo) {
             if (this._attachedMesh) {
                 this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
+            } else if (this._attachedNode) {
+                this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
             }
-            this.gizmos.boundingBoxGizmo.attachedMesh = null;
+            this.gizmos.boundingBoxGizmo.attachedNode = null;
         }
         this._gizmosEnabled.boundingBoxGizmo = value;
     }

+ 1 - 0
src/Gizmos/index.ts

@@ -8,4 +8,5 @@ export * from "./positionGizmo";
 export * from "./rotationGizmo";
 export * from "./scaleGizmo";
 export * from "./lightGizmo";
+export * from "./cameraGizmo";
 export * from "./planeDragGizmo";

+ 14 - 0
src/Loading/Plugins/babylonFileLoader.ts

@@ -29,6 +29,7 @@ import { ReflectionProbe } from "../../Probes/reflectionProbe";
 import { _TypeStore } from '../../Misc/typeStore';
 import { Tools } from '../../Misc/tools';
 import { StringTools } from '../../Misc/stringTools';
+import { PostProcess } from '../../PostProcesses/postProcess';
 
 /** @hidden */
 export var _BabylonLoaderRegistered = true;
@@ -315,6 +316,19 @@ var loadAssetContainer = (scene: Scene, data: string, rootUrl: string, onError?:
             }
         }
 
+        // Postprocesses
+        if (parsedData.postProcesses !== undefined && parsedData.postProcesses !== null) {
+            for (index = 0, cache = parsedData.postProcesses.length; index < cache; index++) {
+                var parsedPostProcess = parsedData.postProcesses[index];
+                var postProcess = PostProcess.Parse(parsedPostProcess, scene, rootUrl);
+                if (postProcess) {
+                    container.postProcesses.push(postProcess);
+                    log += (index === 0 ? "\n\Postprocesses:" : "");
+                    log += "\n\t\t" + postProcess.toString();
+                }
+            }
+        }
+
         // Animation Groups
         if (parsedData.animationGroups !== undefined && parsedData.animationGroups !== null) {
             for (index = 0, cache = parsedData.animationGroups.length; index < cache; index++) {

+ 14 - 0
src/Meshes/instancedMesh.ts

@@ -11,6 +11,7 @@ import { DeepCopier } from "../Misc/deepCopier";
 import { TransformNode } from './transformNode';
 import { Light } from '../Lights/light';
 import { VertexBuffer } from './buffer';
+import { BoundingInfo } from '../Culling/boundingInfo';
 
 Mesh._instancedMeshFactory = (name: string, mesh: Mesh): InstancedMesh => {
     let instance = new InstancedMesh(name, mesh);
@@ -409,6 +410,19 @@ export class InstancedMesh extends AbstractMesh {
         return this._sourceMesh._generatePointsArray();
     }
 
+    /** @hidden */
+    public _updateBoundingInfo(): AbstractMesh {
+        const effectiveMesh = this as AbstractMesh;
+        if (this._boundingInfo) {
+            this._boundingInfo.update(effectiveMesh.worldMatrixFromCache);
+        }
+        else {
+            this._boundingInfo = new BoundingInfo(this.absolutePosition, this.absolutePosition, effectiveMesh.worldMatrixFromCache);
+        }
+        this._updateSubMeshesBoundingInfo(effectiveMesh.worldMatrixFromCache);
+        return this;
+    }
+
     /**
      * Creates a new InstancedMesh from the current mesh.
      * - name (string) : the cloned mesh name

+ 6 - 2
src/Misc/sceneRecorder.ts

@@ -11,6 +11,7 @@ import { TransformNode } from '../Meshes/transformNode';
 import { ParticleSystem } from '../Particles/particleSystem';
 import { MorphTargetManager } from '../Morph/morphTargetManager';
 import { ShadowGenerator } from '../Lights/Shadows/shadowGenerator';
+import { PostProcess } from '../PostProcesses/postProcess';
 
 /**
  * Class used to record delta files between 2 scene states
@@ -89,7 +90,7 @@ export class SceneRecorder {
                         deltaJSON[key] = [];
                     }
                     newObject.__state = {
-                        id: currentObject.id
+                        id: currentObject.id || currentObject.name
                     };
                     deltaJSON[key].push(newObject);
                 }
@@ -97,7 +98,7 @@ export class SceneRecorder {
                 // We need to delete
                 let newObject: any = {
                     __state: {
-                        deleteId: originalObject.id
+                        deleteId: originalObject.id || originalObject.name
                     }
                 };
                 deltaJSON[key].push(newObject);
@@ -231,6 +232,9 @@ export class SceneRecorder {
                     case "morphTargetManagers":
                         this._ApplyDeltaForEntity(source, scene, scene.getMorphTargetById.bind(scene), (data) => MorphTargetManager.Parse(data, scene));
                         break;
+                    case "postProcesses":
+                        this._ApplyDeltaForEntity(source, scene, scene.getPostProcessByName.bind(scene), (data) => PostProcess.Parse(data, scene, ""));
+                        break;
                 }
             } else if (!isNaN(property)) {
                 anyScene[prop] = source;

+ 6 - 0
src/Misc/sceneSerializer.ts

@@ -296,6 +296,12 @@ export class SceneSerializer {
             serializationObject.particleSystems.push(scene.particleSystems[index].serialize(false));
         }
 
+        // Post processes
+        serializationObject.postProcesses = [];
+        for (index = 0; index < scene.postProcesses.length; index++) {
+            serializationObject.postProcesses.push(scene.postProcesses[index].serialize());
+        }
+
         // Action Manager
         if (scene.actionManager) {
             serializationObject.actions = scene.actionManager.serialize("scene");

+ 2 - 2
src/Particles/gpuParticleSystem.ts

@@ -709,9 +709,9 @@ export class GPUParticleSystem extends BaseParticleSystem implements IDisposable
     }>, sceneOrEngine: Scene | ThinEngine, isAnimationSheetEnabled: boolean = false, customEffect: Nullable<Effect> = null) {
         super(name);
 
-        if (sceneOrEngine.getClassName() === "Scene") {
+        if (!sceneOrEngine || sceneOrEngine.getClassName() === "Scene") {
             this._scene = (sceneOrEngine as Scene) || EngineStore.LastCreatedScene;
-            this._engine = this._engine;
+            this._engine = this._scene.getEngine();
             this.uniqueId = this._scene.getUniqueId();
             this._scene.particleSystems.push(this);
         } else {

+ 11 - 0
src/PostProcesses/anaglyphPostProcess.ts

@@ -5,6 +5,7 @@ import { Camera } from "../Cameras/camera";
 import { Effect } from "../Materials/effect";
 
 import "../Shaders/anaglyph.fragment";
+import { _TypeStore } from '../Misc/typeStore';
 
 /**
  * Postprocess used to generate anaglyphic rendering
@@ -13,6 +14,14 @@ export class AnaglyphPostProcess extends PostProcess {
     private _passedProcess: Nullable<PostProcess>;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "AnaglyphPostProcess" string
+     */
+    public getClassName(): string {
+        return "AnaglyphPostProcess";
+    }
+
+    /**
      * Creates a new AnaglyphPostProcess
      * @param name defines postprocess name
      * @param options defines creation options or target ratio scale
@@ -30,3 +39,5 @@ export class AnaglyphPostProcess extends PostProcess {
         });
     }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.AnaglyphPostProcess"] = AnaglyphPostProcess;

+ 26 - 0
src/PostProcesses/blackAndWhitePostProcess.ts

@@ -4,6 +4,11 @@ import { Effect } from "../Materials/effect";
 import { Engine } from "../Engines/engine";
 
 import "../Shaders/blackAndWhite.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize, SerializationHelper } from '../Misc/decorators';
+import { Nullable } from '../types';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * Post process used to render in black and white
@@ -12,9 +17,18 @@ export class BlackAndWhitePostProcess extends PostProcess {
     /**
      * Linear about to convert he result to black and white (default: 1)
      */
+    @serialize()
     public degree = 1;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "BlackAndWhitePostProcess" string
+     */
+    public getClassName(): string {
+        return "BlackAndWhitePostProcess";
+    }
+
+    /**
      * Creates a black and white post process
      * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#black-and-white
      * @param name The name of the effect.
@@ -31,4 +45,16 @@ export class BlackAndWhitePostProcess extends PostProcess {
             effect.setFloat("degree", this.degree);
         });
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<BlackAndWhitePostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new BlackAndWhitePostProcess(
+                parsedPostProcess.name, parsedPostProcess.options,
+                targetCamera, parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.BlackAndWhitePostProcess"] = BlackAndWhitePostProcess;

+ 18 - 1
src/PostProcesses/bloomMergePostProcess.ts

@@ -6,11 +6,25 @@ import { Camera } from "../Cameras/camera";
 import { Constants } from "../Engines/constants";
 
 import "../Shaders/bloomMerge.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize } from '../Misc/decorators';
 
 /**
  * The BloomMergePostProcess merges blurred images with the original based on the values of the circle of confusion.
  */
 export class BloomMergePostProcess extends PostProcess {
+    /** Weight of the bloom to be added to the original input. */
+    @serialize()
+    public weight = 1;
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "BloomMergePostProcess" string
+     */
+    public getClassName(): string {
+        return "BloomMergePostProcess";
+    }
+
     /**
      * Creates a new instance of @see BloomMergePostProcess
      * @param name The name of the effect.
@@ -27,10 +41,11 @@ export class BloomMergePostProcess extends PostProcess {
      */
     constructor(name: string, originalFromInput: PostProcess, blurred: PostProcess,
         /** Weight of the bloom to be added to the original input. */
-        public weight: number,
+        weight: number,
         options: number | PostProcessOptions,
         camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
         super(name, "bloomMerge", ["bloomWeight"], ["circleOfConfusionSampler", "blurStep0", "blurStep1", "blurStep2", "bloomBlur"], options, camera, samplingMode, engine, reusable, null, textureType, undefined, null, true);
+        this.weight = weight;
         this.onApplyObservable.add((effect: Effect) => {
             effect.setTextureFromPostProcess("textureSampler", originalFromInput);
             effect.setTextureFromPostProcessOutput("bloomBlur", blurred);
@@ -42,3 +57,5 @@ export class BloomMergePostProcess extends PostProcess {
         }
     }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.BloomMergePostProcess"] = BloomMergePostProcess;

+ 33 - 2
src/PostProcesses/blurPostProcess.ts

@@ -9,16 +9,27 @@ import { Constants } from "../Engines/constants";
 
 import "../Shaders/kernelBlur.fragment";
 import "../Shaders/kernelBlur.vertex";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize, serializeAsVector2, SerializationHelper } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * The Blur Post Process which blurs an image based on a kernel and direction.
  * Can be used twice in x and y directions to perform a guassian blur in two passes.
  */
 export class BlurPostProcess extends PostProcess {
+    @serialize("kernel")
     protected _kernel: number;
     protected _idealKernel: number;
+    @serialize("packedFloat")
     protected _packedFloat: boolean = false;
     private _staticDefines: string = "";
+
+    /** The direction in which to blur the image. */
+    @serializeAsVector2()
+    public direction: Vector2;
+
     /**
      * Sets the length in pixels of the blur sample region
      */
@@ -63,6 +74,14 @@ export class BlurPostProcess extends PostProcess {
     }
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "BlurPostProcess" string
+     */
+    public getClassName(): string {
+        return "BlurPostProcess";
+    }
+
+    /**
      * Creates a new instance BlurPostProcess
      * @param name The name of the effect.
      * @param direction The direction in which to blur the image.
@@ -76,11 +95,11 @@ export class BlurPostProcess extends PostProcess {
      * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
      */
     constructor(name: string,
-        /** The direction in which to blur the image. */
-        public direction: Vector2,
+        direction: Vector2,
         kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode: number = Texture.BILINEAR_SAMPLINGMODE, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, defines = "", private blockCompilation = false) {
         super(name, "kernelBlur", ["delta", "direction", "cameraMinMaxZ"], ["circleOfConfusionSampler"], options, camera, samplingMode, engine, reusable, null, textureType, "kernelBlur", { varyingCount: 0, depCount: 0 }, true);
         this._staticDefines = defines;
+        this.direction = direction;
         this.onApplyObservable.add((effect: Effect) => {
             if (this._outputTexture) {
                 effect.setFloat2('delta', (1 / this._outputTexture.width) * this.direction.x, (1 / this._outputTexture.height) * this.direction.y);
@@ -254,4 +273,16 @@ export class BlurPostProcess extends PostProcess {
     protected _glslFloat(x: number, decimalFigures = 8) {
         return x.toFixed(decimalFigures).replace(/0+$/, '');
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<BlurPostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new BlurPostProcess(
+                parsedPostProcess.name, parsedPostProcess.direction, parsedPostProcess.kernel,
+                parsedPostProcess.options, targetCamera, parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable, parsedPostProcess.textureType, undefined, false);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.BlurPostProcess"] = BlurPostProcess;

+ 43 - 0
src/PostProcesses/chromaticAberrationPostProcess.ts

@@ -7,6 +7,10 @@ import { Engine } from "../Engines/engine";
 import { Constants } from "../Engines/constants";
 
 import "../Shaders/chromaticAberration.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize, SerializationHelper } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * The ChromaticAberrationPostProcess separates the rgb channels in an image to produce chromatic distortion around the edges of the screen
@@ -15,23 +19,43 @@ export class ChromaticAberrationPostProcess extends PostProcess {
     /**
      * The amount of seperation of rgb channels (default: 30)
      */
+    @serialize()
     aberrationAmount = 30;
 
     /**
      * The amount the effect will increase for pixels closer to the edge of the screen. (default: 0)
      */
+    @serialize()
     radialIntensity = 0;
 
     /**
      * The normilized direction in which the rgb channels should be seperated. If set to 0,0 radial direction will be used. (default: Vector2(0.707,0.707))
      */
+    @serialize()
     direction = new Vector2(0.707, 0.707);
 
     /**
      * The center position where the radialIntensity should be around. [0.5,0.5 is center of screen, 1,1 is top right corder] (default: Vector2(0.5 ,0.5))
      */
+    @serialize()
     centerPosition = new Vector2(0.5, 0.5);
 
+    /** The width of the screen to apply the effect on */
+    @serialize()
+    screenWidth: number;
+
+    /** The height of the screen to apply the effect on */
+    @serialize()
+    screenHeight: number;
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "ChromaticAberrationPostProcess" string
+     */
+    public getClassName(): string {
+        return "ChromaticAberrationPostProcess";
+    }
+
     /**
      * Creates a new instance ChromaticAberrationPostProcess
      * @param name The name of the effect.
@@ -47,6 +71,10 @@ export class ChromaticAberrationPostProcess extends PostProcess {
      */
     constructor(name: string, screenWidth: number, screenHeight: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
         super(name, "chromaticAberration", ["chromatic_aberration", "screen_width", "screen_height", "direction", "radialIntensity", "centerPosition"], [], options, camera, samplingMode, engine, reusable, null, textureType, undefined, null, blockCompilation);
+
+        this.screenWidth = screenWidth;
+        this.screenHeight = screenHeight;
+
         this.onApplyObservable.add((effect: Effect) => {
             effect.setFloat('chromatic_aberration', this.aberrationAmount);
             effect.setFloat('screen_width', screenWidth);
@@ -56,4 +84,19 @@ export class ChromaticAberrationPostProcess extends PostProcess {
             effect.setFloat2('centerPosition', this.centerPosition.x, this.centerPosition.y);
         });
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ChromaticAberrationPostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new ChromaticAberrationPostProcess(
+                parsedPostProcess.name,
+                parsedPostProcess.screenWidth, parsedPostProcess.screenHeight,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable,
+                parsedPostProcess.textureType, false);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.ChromaticAberrationPostProcess"] = ChromaticAberrationPostProcess;

+ 16 - 0
src/PostProcesses/circleOfConfusionPostProcess.ts

@@ -8,6 +8,8 @@ import { Logger } from "../Misc/logger";
 import { Constants } from "../Engines/constants";
 
 import "../Shaders/circleOfConfusion.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize } from '../Misc/decorators';
 
 /**
  * The CircleOfConfusionPostProcess computes the circle of confusion value for each pixel given required lens parameters. See https://en.wikipedia.org/wiki/Circle_of_confusion
@@ -16,20 +18,32 @@ export class CircleOfConfusionPostProcess extends PostProcess {
     /**
      * Max lens size in scene units/1000 (eg. millimeter). Standard cameras are 50mm. (default: 50) The diamater of the resulting aperture can be computed by lensSize/fStop.
      */
+    @serialize()
     public lensSize = 50;
     /**
      * F-Stop of the effect's camera. The diamater of the resulting aperture can be computed by lensSize/fStop. (default: 1.4)
      */
+    @serialize()
     public fStop = 1.4;
     /**
      * Distance away from the camera to focus on in scene units/1000 (eg. millimeter). (default: 2000)
      */
+    @serialize()
     public focusDistance = 2000;
     /**
      * Focal length of the effect's camera in scene units/1000 (eg. millimeter). (default: 50)
      */
+    @serialize()
     public focalLength = 50;
 
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "CircleOfConfusionPostProcess" string
+     */
+    public getClassName(): string {
+        return "CircleOfConfusionPostProcess";
+    }
+
     private _depthTexture: Nullable<RenderTargetTexture> = null;
     /**
      * Creates a new instance CircleOfConfusionPostProcess
@@ -70,3 +84,5 @@ export class CircleOfConfusionPostProcess extends PostProcess {
         this._depthTexture = value;
     }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.CircleOfConfusionPostProcess"] = CircleOfConfusionPostProcess;

+ 34 - 0
src/PostProcesses/colorCorrectionPostProcess.ts

@@ -5,6 +5,11 @@ import { Engine } from "../Engines/engine";
 import { Camera } from "../Cameras/camera";
 
 import "../Shaders/colorCorrection.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { SerializationHelper, serialize } from '../Misc/decorators';
+import { Nullable } from '../types';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  *
@@ -25,6 +30,20 @@ export class ColorCorrectionPostProcess extends PostProcess {
 
     private _colorTableTexture: Texture;
 
+    /**
+     * Gets the color table url used to create the LUT texture
+     */
+    @serialize()
+    public colorTableUrl: string;
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "ColorCorrectionPostProcess" string
+     */
+    public getClassName(): string {
+        return "ColorCorrectionPostProcess";
+    }
+
     constructor(name: string, colorTableUrl: string, options: number | PostProcessOptions, camera: Camera, samplingMode?: number, engine?: Engine, reusable?: boolean) {
         super(name, 'colorCorrection', null, ['colorTable'], options, camera, samplingMode, engine, reusable);
 
@@ -33,8 +52,23 @@ export class ColorCorrectionPostProcess extends PostProcess {
         this._colorTableTexture.wrapU = Texture.CLAMP_ADDRESSMODE;
         this._colorTableTexture.wrapV = Texture.CLAMP_ADDRESSMODE;
 
+        this.colorTableUrl = colorTableUrl;
+
         this.onApply = (effect: Effect) => {
             effect.setTexture("colorTable", this._colorTableTexture);
         };
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ColorCorrectionPostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new ColorCorrectionPostProcess(
+                parsedPostProcess.name, parsedPostProcess.colorTableUrl,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.ColorCorrectionPostProcess"] = ColorCorrectionPostProcess;

+ 31 - 3
src/PostProcesses/convolutionPostProcess.ts

@@ -6,6 +6,10 @@ import { Effect } from "../Materials/effect";
 import { Constants } from "../Engines/constants";
 
 import "../Shaders/convolution.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize, SerializationHelper } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * The ConvolutionPostProcess applies a 3x3 kernel to every pixel of the
@@ -13,6 +17,18 @@ import "../Shaders/convolution.fragment";
  * See http://en.wikipedia.org/wiki/Kernel_(image_processing)
  */
 export class ConvolutionPostProcess extends PostProcess {
+    /** Array of 9 values corresponding to the 3x3 kernel to be applied */
+    @serialize()
+    public kernel: number[];
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "ConvolutionPostProcess" string
+     */
+    public getClassName(): string {
+        return "ConvolutionPostProcess";
+    }
+
     /**
      * Creates a new instance ConvolutionPostProcess
      * @param name The name of the effect.
@@ -25,17 +41,27 @@ export class ConvolutionPostProcess extends PostProcess {
      * @param textureType Type of textures used when performing the post process. (default: 0)
      */
     constructor(name: string,
-        /** Array of 9 values corresponding to the 3x3 kernel to be applied */
-        public kernel: number[],
+        kernel: number[],
         options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT) {
         super(name, "convolution", ["kernel", "screenSize"], null, options, camera, samplingMode, engine, reusable, null, textureType);
-
+            this.kernel = kernel;
         this.onApply = (effect: Effect) => {
             effect.setFloat2("screenSize", this.width, this.height);
             effect.setArray("kernel", this.kernel);
         };
     }
 
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<ConvolutionPostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new ConvolutionPostProcess(
+                parsedPostProcess.name, parsedPostProcess.kernel,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable, parsedPostProcess.textureType);
+        }, parsedPostProcess, scene, rootUrl);
+    }
+
     // Statics
     /**
      * Edge detection 0 see https://en.wikipedia.org/wiki/Kernel_(image_processing)
@@ -62,3 +88,5 @@ export class ConvolutionPostProcess extends PostProcess {
      */
     public static GaussianKernel = [0, 1, 0, 1, 1, 1, 0, 1, 0];
 }
+
+_TypeStore.RegisteredTypes["BABYLON.ConvolutionPostProcess"] = ConvolutionPostProcess;

+ 21 - 1
src/PostProcesses/depthOfFieldBlurPostProcess.ts

@@ -8,6 +8,8 @@ import { BlurPostProcess } from "./blurPostProcess";
 import { Engine } from "../Engines/engine";
 import { Scene } from "../scene";
 import { Constants } from "../Engines/constants";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize } from '../Misc/decorators';
 
 /**
  * The DepthOfFieldBlurPostProcess applied a blur in a give direction.
@@ -17,6 +19,20 @@ import { Constants } from "../Engines/constants";
  */
 export class DepthOfFieldBlurPostProcess extends BlurPostProcess {
     /**
+     * The direction the blur should be applied
+     */
+    @serialize()
+    public direction: Vector2;
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "DepthOfFieldBlurPostProcess" string
+     */
+    public getClassName(): string {
+        return "DepthOfFieldBlurPostProcess";
+    }
+
+    /**
      * Creates a new instance CircleOfConfusionPostProcess
      * @param name The name of the effect.
      * @param scene The scene the effect belongs to.
@@ -32,9 +48,11 @@ export class DepthOfFieldBlurPostProcess extends BlurPostProcess {
      * @param textureType Type of textures used when performing the post process. (default: 0)
      * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: false)
      */
-    constructor(name: string, scene: Scene, public direction: Vector2, kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, circleOfConfusion: PostProcess, imageToBlur: Nullable<PostProcess> = null, samplingMode: number = Texture.BILINEAR_SAMPLINGMODE, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
+    constructor(name: string, scene: Scene, direction: Vector2, kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, circleOfConfusion: PostProcess, imageToBlur: Nullable<PostProcess> = null, samplingMode: number = Texture.BILINEAR_SAMPLINGMODE, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
         super(name, direction, kernel, options, camera, samplingMode = Constants.TEXTURE_BILINEAR_SAMPLINGMODE, engine, reusable, textureType = Constants.TEXTURETYPE_UNSIGNED_INT, `#define DOF 1\r\n`, blockCompilation);
 
+        this.direction = direction;
+
         this.onApplyObservable.add((effect: Effect) => {
             if (imageToBlur != null) {
                 effect.setTextureFromPostProcess("textureSampler", imageToBlur);
@@ -46,3 +64,5 @@ export class DepthOfFieldBlurPostProcess extends BlurPostProcess {
         });
     }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.DepthOfFieldBlurPostProcess"] = DepthOfFieldBlurPostProcess;

+ 8 - 0
src/PostProcesses/depthOfFieldMergePostProcess.ts

@@ -36,6 +36,14 @@ export class DepthOfFieldMergePostProcessOptions {
  */
 export class DepthOfFieldMergePostProcess extends PostProcess {
     /**
+     * Gets a string identifying the name of the class
+     * @returns "DepthOfFieldMergePostProcess" string
+     */
+    public getClassName(): string {
+        return "DepthOfFieldMergePostProcess";
+    }
+
+    /**
      * Creates a new instance of DepthOfFieldMergePostProcess
      * @param name The name of the effect.
      * @param originalFromInput Post process which's input will be used for the merge.

+ 25 - 0
src/PostProcesses/displayPassPostProcess.ts

@@ -4,12 +4,24 @@ import { PostProcess, PostProcessOptions } from "./postProcess";
 import { Engine } from "../Engines/engine";
 
 import "../Shaders/displayPass.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { SerializationHelper } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * DisplayPassPostProcess which produces an output the same as it's input
  */
 export class DisplayPassPostProcess extends PostProcess {
     /**
+     * Gets a string identifying the name of the class
+     * @returns "DisplayPassPostProcess" string
+     */
+    public getClassName(): string {
+        return "DisplayPassPostProcess";
+    }
+
+    /**
      * Creates the DisplayPassPostProcess
      * @param name The name of the effect.
      * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -21,4 +33,17 @@ export class DisplayPassPostProcess extends PostProcess {
     constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean) {
         super(name, "displayPass", ["passSampler"], ["passSampler"], options, camera, samplingMode, engine, reusable);
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<DisplayPassPostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new DisplayPassPostProcess(
+                parsedPostProcess.name,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.DisplayPassPostProcess"] = DisplayPassPostProcess;

+ 15 - 0
src/PostProcesses/extractHighlightsPostProcess.ts

@@ -7,6 +7,8 @@ import { ToGammaSpace } from "../Maths/math.constants";
 import { Constants } from "../Engines/constants";
 
 import "../Shaders/extractHighlights.fragment";
+import { serialize } from '../Misc/decorators';
+import { _TypeStore } from '../Misc/typeStore';
 
 /**
  * The extract highlights post process sets all pixels to black except pixels above the specified luminance threshold. Used as the first step for a bloom effect.
@@ -15,15 +17,26 @@ export class ExtractHighlightsPostProcess extends PostProcess {
     /**
      * The luminance threshold, pixels below this value will be set to black.
      */
+    @serialize()
     public threshold = 0.9;
 
     /** @hidden */
     public _exposure = 1;
+
     /**
      * Post process which has the input texture to be used when performing highlight extraction
      * @hidden
      */
     public _inputPostProcess: Nullable<PostProcess> = null;
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "ExtractHighlightsPostProcess" string
+     */
+    public getClassName(): string {
+        return "ExtractHighlightsPostProcess";
+    }
+
     constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
         super(name, "extractHighlights", ["threshold", "exposure"], null, options, camera, samplingMode, engine, reusable, null, textureType, undefined, null, blockCompilation);
         this.onApplyObservable.add((effect: Effect) => {
@@ -35,3 +48,5 @@ export class ExtractHighlightsPostProcess extends PostProcess {
         });
     }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.ExtractHighlightsPostProcess"] = ExtractHighlightsPostProcess;

+ 31 - 2
src/PostProcesses/filterPostProcess.ts

@@ -6,11 +6,27 @@ import { PostProcess, PostProcessOptions } from "./postProcess";
 import { Engine } from "../Engines/engine";
 
 import "../Shaders/filter.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serializeAsMatrix, SerializationHelper } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * Applies a kernel filter to the image
  */
 export class FilterPostProcess extends PostProcess {
+    /** The matrix to be applied to the image */
+    @serializeAsMatrix()
+    public kernelMatrix: Matrix;
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "FilterPostProcess" string
+     */
+    public getClassName(): string {
+        return "FilterPostProcess";
+    }
+
     /**
      *
      * @param name The name of the effect.
@@ -22,8 +38,7 @@ export class FilterPostProcess extends PostProcess {
      * @param reusable If the post process can be reused on the same frame. (default: false)
      */
     constructor(name: string,
-        /** The matrix to be applied to the image */
-        public kernelMatrix: Matrix,
+        kernelMatrix: Matrix,
         options: number | PostProcessOptions,
         camera: Nullable<Camera>,
         samplingMode?: number,
@@ -31,9 +46,23 @@ export class FilterPostProcess extends PostProcess {
         reusable?: boolean
     ) {
         super(name, "filter", ["kernelMatrix"], null, options, camera, samplingMode, engine, reusable);
+        this.kernelMatrix = kernelMatrix;
 
         this.onApply = (effect: Effect) => {
             effect.setMatrix("kernelMatrix", this.kernelMatrix);
         };
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<FilterPostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new FilterPostProcess(
+                parsedPostProcess.name, parsedPostProcess.kernelMatrix,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.FilterPostProcess"] = FilterPostProcess;

+ 23 - 4
src/PostProcesses/fxaaPostProcess.ts

@@ -8,16 +8,22 @@ import { Constants } from "../Engines/constants";
 
 import "../Shaders/fxaa.fragment";
 import "../Shaders/fxaa.vertex";
+import { _TypeStore } from '../Misc/typeStore';
+import { SerializationHelper } from '../Misc/decorators';
 
+declare type Scene = import("../scene").Scene;
 /**
  * Fxaa post process
  * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#fxaa
  */
 export class FxaaPostProcess extends PostProcess {
-    /** @hidden */
-    public texelWidth: number;
-    /** @hidden */
-    public texelHeight: number;
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "FxaaPostProcess" string
+     */
+    public getClassName(): string {
+        return "FxaaPostProcess";
+    }
 
     constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera> = null, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT) {
         super(name, "fxaa", ["texelSize"], null, options, camera, samplingMode || Texture.BILINEAR_SAMPLINGMODE, engine, reusable, null, textureType, "fxaa", undefined, true);
@@ -44,4 +50,17 @@ export class FxaaPostProcess extends PostProcess {
 
         return null;
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new FxaaPostProcess(
+                parsedPostProcess.name,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.FxaaPostProcess"] = FxaaPostProcess;

+ 27 - 0
src/PostProcesses/grainPostProcess.ts

@@ -6,6 +6,10 @@ import { Engine } from "../Engines/engine";
 import { Constants } from "../Engines/constants";
 
 import "../Shaders/grain.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize, SerializationHelper } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * The GrainPostProcess adds noise to the image at mid luminance levels
@@ -14,13 +18,23 @@ export class GrainPostProcess extends PostProcess {
     /**
      * The intensity of the grain added (default: 30)
      */
+    @serialize()
     public intensity: number = 30;
     /**
      * If the grain should be randomized on every frame
      */
+    @serialize()
     public animated: boolean = false;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "GrainPostProcess" string
+     */
+    public getClassName(): string {
+        return "GrainPostProcess";
+    }
+
+    /**
      * Creates a new instance of @see GrainPostProcess
      * @param name The name of the effect.
      * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -38,4 +52,17 @@ export class GrainPostProcess extends PostProcess {
             effect.setFloat('animatedSeed', this.animated ? Math.random() + 1 : 1);
         });
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new GrainPostProcess(
+                parsedPostProcess.name,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.GrainPostProcess"] = GrainPostProcess;

+ 8 - 0
src/PostProcesses/highlightsPostProcess.ts

@@ -12,6 +12,14 @@ import "../Shaders/highlights.fragment";
  */
 export class HighlightsPostProcess extends PostProcess {
     /**
+     * Gets a string identifying the name of the class
+     * @returns "HighlightsPostProcess" string
+     */
+    public getClassName(): string {
+        return "HighlightsPostProcess";
+    }
+
+    /**
      * Extracts highlights from the image
      * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses
      * @param name The name of the effect.

+ 0 - 1
src/PostProcesses/imageProcessingPostProcess.ts

@@ -20,7 +20,6 @@ import "../Shaders/postprocess.vertex";
  * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#imageprocessing
  */
 export class ImageProcessingPostProcess extends PostProcess {
-
     /**
      * Default configuration related to image processing available in the PBR Material.
      */

+ 26 - 1
src/PostProcesses/motionBlurPostProcess.ts

@@ -6,14 +6,16 @@ import { Effect } from "../Materials/effect";
 import { PostProcess, PostProcessOptions } from "./postProcess";
 import { Constants } from "../Engines/constants";
 import { GeometryBufferRenderer } from "../Rendering/geometryBufferRenderer";
-import { Scene } from "../scene";
 import { AbstractMesh } from "../Meshes/abstractMesh";
 
 import "../Animations/animatable";
 import '../Rendering/geometryBufferRendererSceneComponent';
 import "../Shaders/motionBlur.fragment";
+import { serialize, SerializationHelper } from '../Misc/decorators';
+import { _TypeStore } from '../Misc/typeStore';
 
 declare type Engine = import("../Engines/engine").Engine;
+declare type Scene = import("../scene").Scene;
 
 /**
  * The Motion Blur Post Process which blurs an image based on the objects velocity in scene.
@@ -31,6 +33,7 @@ export class MotionBlurPostProcess extends PostProcess {
     /**
      * Defines how much the image is blurred by the movement. Default value is equal to 1
      */
+    @serialize()
     public motionStrength: number = 1;
 
     /**
@@ -51,10 +54,19 @@ export class MotionBlurPostProcess extends PostProcess {
         }
     }
 
+    @serialize("motionBlurSamples")
     private _motionBlurSamples: number = 32;
     private _geometryBufferRenderer: Nullable<GeometryBufferRenderer>;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "MotionBlurPostProcess" string
+     */
+    public getClassName(): string {
+        return "MotionBlurPostProcess";
+    }
+
+    /**
      * Creates a new instance MotionBlurPostProcess
      * @param name The name of the effect.
      * @param scene The scene containing the objects to blur according to their velocity.
@@ -132,4 +144,17 @@ export class MotionBlurPostProcess extends PostProcess {
 
         super.dispose(camera);
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string): Nullable<MotionBlurPostProcess> {
+        return SerializationHelper.Parse(() => {
+            return new MotionBlurPostProcess(
+                parsedPostProcess.name, scene, parsedPostProcess.options,
+                targetCamera, parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable,
+                parsedPostProcess.textureType, false);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.MotionBlurPostProcess"] = MotionBlurPostProcess;

+ 44 - 0
src/PostProcesses/passPostProcess.ts

@@ -6,12 +6,24 @@ import { Engine } from "../Engines/engine";
 
 import "../Shaders/pass.fragment";
 import "../Shaders/passCube.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { SerializationHelper } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * PassPostProcess which produces an output the same as it's input
  */
 export class PassPostProcess extends PostProcess {
     /**
+     * Gets a string identifying the name of the class
+     * @returns "PassPostProcess" string
+     */
+    public getClassName(): string {
+        return "PassPostProcess";
+    }
+
+    /**
      * Creates the PassPostProcess
      * @param name The name of the effect.
      * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -25,8 +37,21 @@ export class PassPostProcess extends PostProcess {
     constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera> = null, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
         super(name, "pass", null, null, options, camera, samplingMode, engine, reusable, undefined, textureType, undefined, null, blockCompilation);
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new PassPostProcess(
+                parsedPostProcess.name,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
 
+_TypeStore.RegisteredTypes["BABYLON.PassPostProcess"] = PassPostProcess;
+
 /**
  * PassCubePostProcess which produces an output the same as it's input (which must be a cube texture)
  */
@@ -75,6 +100,14 @@ export class PassCubePostProcess extends PostProcess {
     }
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "PassCubePostProcess" string
+     */
+    public getClassName(): string {
+        return "PassCubePostProcess";
+    }
+
+    /**
      * Creates the PassCubePostProcess
      * @param name The name of the effect.
      * @param options The required width/height ratio to downsize to before computing the render pass.
@@ -88,6 +121,17 @@ export class PassCubePostProcess extends PostProcess {
     constructor(name: string, options: number | PostProcessOptions, camera: Nullable<Camera> = null, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, blockCompilation = false) {
         super(name, "passCube", null, null, options, camera, samplingMode, engine, reusable, "#define POSITIVEX", textureType, undefined, null, blockCompilation);
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new PassCubePostProcess(
+                parsedPostProcess.name,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
 
 Engine._RescalePostProcessFactory = (engine: Engine) => {

+ 93 - 31
src/PostProcesses/postProcess.ts

@@ -12,6 +12,8 @@ import { Color4 } from '../Maths/math.color';
 
 import "../Engines/Extensions/engine.renderTarget";
 import { NodeMaterial } from '../Materials/Node/nodeMaterial';
+import { serialize, serializeAsColor4, SerializationHelper } from '../Misc/decorators';
+import { _TypeStore } from '../Misc/typeStore';
 
 declare type Scene = import("../scene").Scene;
 declare type InternalTexture = import("../Materials/Textures/internalTexture").InternalTexture;
@@ -31,16 +33,23 @@ export class PostProcess {
     /**
      * Gets or sets the unique id of the post process
      */
+    @serialize()
     public uniqueId: number;
 
+    /** Name of the PostProcess. */
+    @serialize()
+    public name: string;
+
     /**
     * Width of the texture to apply the post process on
     */
+    @serialize()
     public width = -1;
 
     /**
     * Height of the texture to apply the post process on
     */
+    @serialize()
     public height = -1;
 
     /**
@@ -57,23 +66,28 @@ export class PostProcess {
     * Sampling mode used by the shader
     * See https://doc.babylonjs.com/classes/3.1/texture
     */
+    @serialize()
     public renderTargetSamplingMode: number;
     /**
     * Clear color to use when screen clearing
     */
+    @serializeAsColor4()
     public clearColor: Color4;
     /**
     * If the buffer needs to be cleared before applying the post process. (default: true)
     * Should be set to false if shader will overwrite all previous pixels.
     */
+    @serialize()
     public autoClear = true;
     /**
     * Type of alpha mode to use when performing the post process (default: Engine.ALPHA_DISABLE)
     */
+    @serialize()
     public alphaMode = Constants.ALPHA_DISABLE;
     /**
     * Sets the setAlphaBlendConstants of the babylon engine
     */
+    @serialize()
     public alphaConstants: Color4;
     /**
     * Animations to be used for the post processing
@@ -84,11 +98,13 @@ export class PostProcess {
      * Enable Pixel Perfect mode where texture is not scaled to be power of 2.
      * Can only be used on a single postprocess or on the last one of a chain. (default: false)
      */
+    @serialize()
     public enablePixelPerfectMode = false;
 
     /**
      * Force the postprocess to be applied without taking in account viewport
      */
+    @serialize()
     public forceFullscreenViewport = true;
 
     /**
@@ -107,13 +123,17 @@ export class PostProcess {
      * | 3     | SCALEMODE_CEILING                   | [engine.scalemode_ceiling](https://doc.babylonjs.com/api/classes/babylon.engine#scalemode_ceiling) |
      *
      */
+    @serialize()
     public scaleMode = Constants.SCALEMODE_FLOOR;
     /**
     * Force textures to be a power of two (default: false)
     */
+    @serialize()
     public alwaysForcePOT = false;
 
+    @serialize("samples")
     private _samples = 1;
+
     /**
     * Number of sample textures (default: 1)
     */
@@ -134,6 +154,7 @@ export class PostProcess {
     /**
     * Modify the scale of the post process to be the same as the viewport (default: false)
     */
+    @serialize()
     public adaptScaleToCurrentViewport = false;
 
     private _camera: Camera;
@@ -320,48 +341,49 @@ export class PostProcess {
      * @param textureFormat Format of textures used when performing the post process. (default: TEXTUREFORMAT_RGBA)
      */
     constructor(
-        /** Name of the PostProcess. */
-        public name: string,
+        name: string,
         fragmentUrl: string, parameters: Nullable<string[]>, samplers: Nullable<string[]>, options: number | PostProcessOptions, camera: Nullable<Camera>,
         samplingMode: number = Constants.TEXTURE_NEAREST_SAMPLINGMODE, engine?: Engine, reusable?: boolean, defines: Nullable<string> = null, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT, vertexUrl: string = "postprocess",
         indexParameters?: any, blockCompilation = false, textureFormat = Constants.TEXTUREFORMAT_RGBA) {
-        if (camera != null) {
-            this._camera = camera;
-            this._scene = camera.getScene();
-            camera.attachPostProcess(this);
-            this._engine = this._scene.getEngine();
-
-            this._scene.postProcesses.push(this);
-            this.uniqueId = this._scene.getUniqueId();
-        }
-        else if (engine) {
-            this._engine = engine;
-            this._engine.postProcesses.push(this);
-        }
-        this._options = options;
-        this.renderTargetSamplingMode = samplingMode ? samplingMode : Constants.TEXTURE_NEAREST_SAMPLINGMODE;
-        this._reusable = reusable || false;
-        this._textureType = textureType;
-        this._textureFormat = textureFormat;
 
-        this._samplers = samplers || [];
-        this._samplers.push("textureSampler");
+                this.name = name;
+            if (camera != null) {
+                this._camera = camera;
+                this._scene = camera.getScene();
+                camera.attachPostProcess(this);
+                this._engine = this._scene.getEngine();
 
-        this._fragmentUrl = fragmentUrl;
-        this._vertexUrl = vertexUrl;
-        this._parameters = parameters || [];
+                this._scene.postProcesses.push(this);
+                this.uniqueId = this._scene.getUniqueId();
+            }
+            else if (engine) {
+                this._engine = engine;
+                this._engine.postProcesses.push(this);
+            }
+            this._options = options;
+            this.renderTargetSamplingMode = samplingMode ? samplingMode : Constants.TEXTURE_NEAREST_SAMPLINGMODE;
+            this._reusable = reusable || false;
+            this._textureType = textureType;
+            this._textureFormat = textureFormat;
 
-        this._parameters.push("scale");
+            this._samplers = samplers || [];
+            this._samplers.push("textureSampler");
 
-        this._indexParameters = indexParameters;
+            this._fragmentUrl = fragmentUrl;
+            this._vertexUrl = vertexUrl;
+            this._parameters = parameters || [];
 
-        if (!blockCompilation) {
-            this.updateEffect(defines);
-        }
+            this._parameters.push("scale");
+
+            this._indexParameters = indexParameters;
+
+            if (!blockCompilation) {
+                this.updateEffect(defines);
+            }
     }
 
     /**
-     * Gets a string idenfifying the name of the class
+     * Gets a string identifying the name of the class
      * @returns "PostProcess" string
      */
     public getClassName(): string {
@@ -697,4 +719,44 @@ export class PostProcess {
         this.onBeforeRenderObservable.clear();
         this.onSizeChangedObservable.clear();
     }
+
+    /**
+     * Serializes the particle system to a JSON object
+     * @returns the JSON object
+     */
+    public serialize(): any {
+        var serializationObject = SerializationHelper.Serialize(this);
+        serializationObject.customType = "BABYLON." + this.getClassName();
+        serializationObject.cameraId = this.getCamera().id;
+        serializationObject.reusable = this._reusable;
+        serializationObject.options = this._options;
+        serializationObject.textureType = this._textureType;
+
+        return serializationObject;
+    }
+
+    /**
+     * Creates a material from parsed material data
+     * @param parsedPostProcess defines parsed post process data
+     * @param scene defines the hosting scene
+     * @param rootUrl defines the root URL to use to load textures
+     * @returns a new post process
+     */
+    public static Parse(parsedPostProcess: any, scene: Scene, rootUrl: string): Nullable<PostProcess> {
+        var postProcessType = _TypeStore.GetClass(parsedPostProcess.customType);
+
+        if (!postProcessType || !postProcessType._Parse) {
+            return null;
+        }
+
+        var camera = scene.getCameraByID(parsedPostProcess.cameraId);
+
+        if (!camera) {
+            return null;
+        }
+
+        return postProcessType._Parse(parsedPostProcess, camera, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.PostProcess"] = PostProcess;

+ 51 - 6
src/PostProcesses/refractionPostProcess.ts

@@ -6,6 +6,10 @@ import { PostProcess, PostProcessOptions } from "./postProcess";
 import { Engine } from "../Engines/engine";
 
 import "../Shaders/refraction.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { SerializationHelper, serialize } from '../Misc/decorators';
+
+declare type Scene = import("../scene").Scene;
 
 /**
  * Post process which applies a refractin texture
@@ -15,6 +19,22 @@ export class RefractionPostProcess extends PostProcess {
     private _refTexture: Texture;
     private _ownRefractionTexture = true;
 
+    /** the base color of the refraction (used to taint the rendering) */
+    @serialize()
+    public color: Color3;
+
+    /** simulated refraction depth */
+    @serialize()
+    public depth: number;
+
+    /** the coefficient of the base color (0 to remove base color tainting) */
+    @serialize()
+    public colorLevel: number;
+
+    /** Gets the url used to load the refraction texture */
+    @serialize()
+    public refractionTextureUrl: string;
+
     /**
      * Gets or sets the refraction texture
      * Please note that you are responsible for disposing the texture if you set it manually
@@ -33,6 +53,14 @@ export class RefractionPostProcess extends PostProcess {
     }
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "RefractionPostProcess" string
+     */
+    public getClassName(): string {
+        return "RefractionPostProcess";
+    }
+
+    /**
      * Initializes the RefractionPostProcess
      * @see https://doc.babylonjs.com/how_to/how_to_use_postprocesses#refraction
      * @param name The name of the effect.
@@ -49,12 +77,9 @@ export class RefractionPostProcess extends PostProcess {
     constructor(
         name: string,
         refractionTextureUrl: string,
-        /** the base color of the refraction (used to taint the rendering) */
-        public color: Color3,
-        /** simulated refraction depth */
-        public depth: number,
-        /** the coefficient of the base color (0 to remove base color tainting) */
-        public colorLevel: number,
+        color: Color3,
+        depth: number,
+        colorLevel: number,
         options: number | PostProcessOptions,
         camera: Camera,
         samplingMode?: number,
@@ -63,6 +88,11 @@ export class RefractionPostProcess extends PostProcess {
     ) {
         super(name, "refraction", ["baseColor", "depth", "colorLevel"], ["refractionSampler"], options, camera, samplingMode, engine, reusable);
 
+        this.color = color;
+        this.depth = depth;
+        this.colorLevel = colorLevel;
+        this.refractionTextureUrl = refractionTextureUrl;
+
         this.onActivateObservable.add((cam: Camera) => {
             this._refTexture = this._refTexture || new Texture(refractionTextureUrl, cam.getScene());
         });
@@ -89,4 +119,19 @@ export class RefractionPostProcess extends PostProcess {
 
         super.dispose(camera);
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new RefractionPostProcess(
+                parsedPostProcess.name, parsedPostProcess.refractionTextureUrl,
+                parsedPostProcess.color, parsedPostProcess.depth,
+                parsedPostProcess.colorLevel,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.RefractionPostProcess"] = RefractionPostProcess;

+ 26 - 1
src/PostProcesses/screenSpaceCurvaturePostProcess.ts

@@ -5,13 +5,15 @@ import { Effect } from "../Materials/effect";
 import { PostProcess, PostProcessOptions } from "./postProcess";
 import { Constants } from "../Engines/constants";
 import { GeometryBufferRenderer } from "../Rendering/geometryBufferRenderer";
-import { Scene } from "../scene";
 
 import '../Rendering/geometryBufferRendererSceneComponent';
 import "../Shaders/screenSpaceCurvature.fragment";
 import { EngineStore } from '../Engines/engineStore';
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize, SerializationHelper } from '../Misc/decorators';
 
 declare type Engine = import("../Engines/engine").Engine;
+declare type Scene = import("../scene").Scene;
 
 /**
  * The Screen Space curvature effect can help highlighting ridge and valley of a model.
@@ -20,16 +22,26 @@ export class ScreenSpaceCurvaturePostProcess extends PostProcess {
     /**
      * Defines how much ridge the curvature effect displays.
      */
+    @serialize()
     public ridge: number = 1;
 
     /**
      * Defines how much valley the curvature effect displays.
      */
+    @serialize()
     public valley: number = 1;
 
     private _geometryBufferRenderer: Nullable<GeometryBufferRenderer>;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "ScreenSpaceCurvaturePostProcess" string
+     */
+    public getClassName(): string {
+        return "ScreenSpaceCurvaturePostProcess";
+    }
+
+    /**
      * Creates a new instance ScreenSpaceCurvaturePostProcess
      * @param name The name of the effect.
      * @param scene The scene containing the objects to blur according to their velocity.
@@ -72,4 +84,17 @@ export class ScreenSpaceCurvaturePostProcess extends PostProcess {
 
         return engine.webGLVersion > 1 || engine.getCaps().drawBuffersExtension;
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new ScreenSpaceCurvaturePostProcess(
+                parsedPostProcess.name, scene,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.textureType, parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.ScreenSpaceCurvaturePostProcess"] = ScreenSpaceCurvaturePostProcess;

+ 25 - 2
src/PostProcesses/screenSpaceReflectionPostProcess.ts

@@ -3,13 +3,15 @@ import { Camera } from "../Cameras/camera";
 import { Effect } from "../Materials/effect";
 import { PostProcess, PostProcessOptions } from "./postProcess";
 import { Constants } from "../Engines/constants";
-import { Scene } from '../scene';
 import { GeometryBufferRenderer } from '../Rendering/geometryBufferRenderer';
-import { serialize } from '../Misc/decorators';
+import { serialize, SerializationHelper } from '../Misc/decorators';
 
 import "../Shaders/screenSpaceReflection.fragment";
+import { _TypeStore } from '../Misc/typeStore';
 
 declare type Engine = import("../Engines/engine").Engine;
+declare type Scene = import("../scene").Scene;
+
 /**
  * The ScreenSpaceReflectionPostProcess performs realtime reflections using only and only the available informations on the screen (positions and normals).
  * Basically, the screen space reflection post-process will compute reflections according the material's reflectivity.
@@ -47,6 +49,14 @@ export class ScreenSpaceReflectionPostProcess extends PostProcess {
     private _smoothSteps: number = 5;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "ScreenSpaceReflectionPostProcess" string
+     */
+    public getClassName(): string {
+        return "ScreenSpaceReflectionPostProcess";
+    }
+
+    /**
      * Creates a new instance of ScreenSpaceReflectionPostProcess.
      * @param name The name of the effect.
      * @param scene The scene containing the objects to calculate reflections.
@@ -194,4 +204,17 @@ export class ScreenSpaceReflectionPostProcess extends PostProcess {
 
         this.updateEffect(defines.join("\n"));
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new ScreenSpaceReflectionPostProcess(
+                parsedPostProcess.name, scene,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.textureType, parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.ScreenSpaceReflectionPostProcess"] = ScreenSpaceReflectionPostProcess;

+ 28 - 0
src/PostProcesses/sharpenPostProcess.ts

@@ -5,8 +5,12 @@ import { PostProcess, PostProcessOptions } from "./postProcess";
 import { Constants } from "../Engines/constants";
 
 import "../Shaders/sharpen.fragment";
+import { _TypeStore } from '../Misc/typeStore';
+import { serialize, SerializationHelper } from '../Misc/decorators';
 
 declare type Engine = import("../Engines/engine").Engine;
+declare type Scene = import("../scene").Scene;
+
 /**
  * The SharpenPostProcess applies a sharpen kernel to every pixel
  * See http://en.wikipedia.org/wiki/Kernel_(image_processing)
@@ -15,11 +19,22 @@ export class SharpenPostProcess extends PostProcess {
     /**
      * How much of the original color should be applied. Setting this to 0 will display edge detection. (default: 1)
      */
+    @serialize()
     public colorAmount: number = 1.0;
     /**
      * How much sharpness should be applied (default: 0.3)
      */
+    @serialize()
     public edgeAmount: number = 0.3;
+
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "SharpenPostProcess" string
+     */
+    public getClassName(): string {
+        return "SharpenPostProcess";
+    }
+
     /**
      * Creates a new instance ConvolutionPostProcess
      * @param name The name of the effect.
@@ -39,4 +54,17 @@ export class SharpenPostProcess extends PostProcess {
             effect.setFloat2("sharpnessAmounts", this.edgeAmount, this.colorAmount);
         };
     }
+
+    /** @hidden */
+    public static _Parse(parsedPostProcess: any, targetCamera: Camera, scene: Scene, rootUrl: string) {
+        return SerializationHelper.Parse(() => {
+            return new SharpenPostProcess(
+                parsedPostProcess.name,
+                parsedPostProcess.options, targetCamera,
+                parsedPostProcess.renderTargetSamplingMode,
+                scene.getEngine(), parsedPostProcess.textureType, parsedPostProcess.reusable);
+        }, parsedPostProcess, scene, rootUrl);
+    }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.SharpenPostProcess"] = SharpenPostProcess;

+ 16 - 0
src/PostProcesses/stereoscopicInterlacePostProcess.ts

@@ -15,6 +15,14 @@ export class StereoscopicInterlacePostProcessI extends PostProcess {
     private _passedProcess: Nullable<PostProcess>;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "StereoscopicInterlacePostProcessI" string
+     */
+    public getClassName(): string {
+        return "StereoscopicInterlacePostProcessI";
+    }
+
+    /**
      * Initializes a StereoscopicInterlacePostProcessI
      * @param name The name of the effect.
      * @param rigCameras The rig cameras to be appled to the post process
@@ -47,6 +55,14 @@ export class StereoscopicInterlacePostProcess extends PostProcess {
     private _passedProcess: Nullable<PostProcess>;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "StereoscopicInterlacePostProcess" string
+     */
+    public getClassName(): string {
+        return "StereoscopicInterlacePostProcess";
+    }
+
+    /**
      * Initializes a StereoscopicInterlacePostProcess
      * @param name The name of the effect.
      * @param rigCameras The rig cameras to be appled to the post process

+ 7 - 5
src/PostProcesses/subSurfaceScatteringPostProcess.ts

@@ -16,10 +16,13 @@ import "../Shaders/postprocess.vertex";
  * Sub surface scattering post process
  */
 export class SubSurfaceScatteringPostProcess extends PostProcess {
-    /** @hidden */
-    public texelWidth: number;
-    /** @hidden */
-    public texelHeight: number;
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "SubSurfaceScatteringPostProcess" string
+     */
+    public getClassName(): string {
+        return "SubSurfaceScatteringPostProcess";
+    }
 
     constructor(name: string, scene: Scene, options: number | PostProcessOptions, camera: Nullable<Camera> = null, samplingMode?: number, engine?: Engine, reusable?: boolean, textureType: number = Constants.TEXTURETYPE_UNSIGNED_INT) {
         super(name, "subSurfaceScattering", ["texelSize", "viewportSize", "metersPerUnit"], ["diffusionS", "diffusionD", "filterRadii", "irradianceSampler", "depthSampler", "albedoSampler"], options, camera, samplingMode || Texture.BILINEAR_SAMPLINGMODE, engine, reusable, null, textureType, "postprocess", undefined, true);
@@ -45,6 +48,5 @@ export class SubSurfaceScatteringPostProcess extends PostProcess {
             effect.setArray("diffusionD", scene.prePassRenderer.subSurfaceConfiguration.ssDiffusionD);
             effect.setArray("filterRadii", scene.prePassRenderer.subSurfaceConfiguration.ssFilterRadii);
         });
-
     }
 }

+ 7 - 0
src/PostProcesses/tonemapPostProcess.ts

@@ -23,6 +23,13 @@ export enum TonemappingOperator {
  * Defines a post process to apply tone mapping
  */
 export class TonemapPostProcess extends PostProcess {
+    /**
+     * Gets a string identifying the name of the class
+     * @returns "TonemapPostProcess" string
+     */
+    public getClassName(): string {
+        return "TonemapPostProcess";
+    }
 
     /**
      * Creates a new TonemapPostProcess

+ 3 - 0
src/PostProcesses/volumetricLightScatteringPostProcess.ts

@@ -25,6 +25,7 @@ import "../Shaders/volumetricLightScatteringPass.vertex";
 import "../Shaders/volumetricLightScatteringPass.fragment";
 import { Color4, Color3 } from '../Maths/math.color';
 import { Viewport } from '../Maths/math.viewport';
+import { _TypeStore } from '../Misc/typeStore';
 
 declare type Engine = import("../Engines/engine").Engine;
 
@@ -484,3 +485,5 @@ export class VolumetricLightScatteringPostProcess extends PostProcess {
         return mesh;
     }
 }
+
+_TypeStore.RegisteredTypes["BABYLON.VolumetricLightScatteringPostProcess"] = VolumetricLightScatteringPostProcess;

+ 8 - 0
src/PostProcesses/vrDistortionCorrectionPostProcess.ts

@@ -20,6 +20,14 @@ export class VRDistortionCorrectionPostProcess extends PostProcess {
     private _lensCenter: Vector2;
 
     /**
+     * Gets a string identifying the name of the class
+     * @returns "VRDistortionCorrectionPostProcess" string
+     */
+    public getClassName(): string {
+        return "VRDistortionCorrectionPostProcess";
+    }
+
+    /**
      * Initializes the VRDistortionCorrectionPostProcess
      * @param name The name of the effect.
      * @param camera The camera to apply the render pass to.

+ 8 - 0
src/PostProcesses/vrMultiviewToSingleviewPostProcess.ts

@@ -12,6 +12,14 @@ import "../Engines/Extensions/engine.multiview";
  */
 export class VRMultiviewToSingleviewPostProcess extends PostProcess {
     /**
+     * Gets a string identifying the name of the class
+     * @returns "VRMultiviewToSingleviewPostProcess" string
+     */
+    public getClassName(): string {
+        return "VRMultiviewToSingleviewPostProcess";
+    }
+
+    /**
      * Initializes a VRMultiviewToSingleview
      * @param name name of the post process
      * @param camera camera to be applied to

+ 6 - 0
src/abstractScene.ts

@@ -17,6 +17,7 @@ import { Light } from "./Lights/light";
 import { Node } from "./node";
 
 declare type Animation = import("./Animations/animation").Animation;
+declare type PostProcess = import("./PostProcesses/postProcess").PostProcess;
 
 /**
  * Defines how the parser contract is defined.
@@ -200,6 +201,11 @@ export abstract class AbstractScene {
     public environmentTexture: Nullable<BaseTexture> = null;
 
     /**
+     * The list of postprocesses added to the scene
+     */
+    public postProcesses = new Array<PostProcess>();
+
+    /**
      * @returns all meshes, lights, cameras, transformNodes and bones
      */
     public getNodes(): Array<Node> {

+ 1 - 1
src/node.ts

@@ -254,7 +254,7 @@ export class Node implements IBehaviorAware<Node> {
     }
 
     /**
-     * Gets a string idenfifying the name of the class
+     * Gets a string identifying the name of the class
      * @returns "Node" string
      */
     public getClassName(): string {

+ 23 - 10
src/scene.ts

@@ -32,7 +32,6 @@ import { ICollisionCoordinator } from "./Collisions/collisionCoordinator";
 import { PointerEventTypes, PointerInfoPre, PointerInfo } from "./Events/pointerEvents";
 import { KeyboardInfoPre, KeyboardInfo } from "./Events/keyboardEvents";
 import { ActionEvent } from "./Actions/actionEvent";
-import { PostProcess } from "./PostProcesses/postProcess";
 import { PostProcessManager } from "./PostProcesses/postProcessManager";
 import { IOfflineProvider } from "./Offline/IOfflineProvider";
 import { RenderingGroupInfo, RenderingManager, IRenderingManagerAutoClearSetup } from "./Rendering/renderingManager";
@@ -64,6 +63,7 @@ declare type Animatable = import("./Animations/animatable").Animatable;
 declare type AnimationGroup = import("./Animations/animationGroup").AnimationGroup;
 declare type AnimationPropertiesOverride = import("./Animations/animationPropertiesOverride").AnimationPropertiesOverride;
 declare type Collider = import("./Collisions/collider").Collider;
+declare type PostProcess = import("./PostProcesses/postProcess").PostProcess;
 
 /**
  * Define an interface for all classes that will hold resources
@@ -1046,10 +1046,6 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
     */
     public postProcessesEnabled = true;
     /**
-     * The list of postprocesses added to the scene
-     */
-    public postProcesses = new Array<PostProcess>();
-    /**
      * Gets the current postprocess manager
      */
     public postProcessManager: PostProcessManager;
@@ -1436,7 +1432,7 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
     }
 
     /**
-     * Gets a string idenfifying the name of the class
+     * Gets a string identifying the name of the class
      * @returns "Scene" string
      */
     public getClassName(): string {
@@ -2872,10 +2868,12 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
 
         if (index !== this.geometries.length - 1) {
             const lastGeometry = this.geometries[this.geometries.length - 1];
-            this.geometries[index] = lastGeometry;
-            if (this.geometriesByUniqueId) {
-                this.geometriesByUniqueId[lastGeometry.uniqueId] = index;
-                this.geometriesByUniqueId[geometry.uniqueId] = undefined;
+            if (lastGeometry) {
+                this.geometries[index] = lastGeometry;
+                if (this.geometriesByUniqueId) {
+                    this.geometriesByUniqueId[lastGeometry.uniqueId] = index;
+                    this.geometriesByUniqueId[geometry.uniqueId] = undefined;
+                }
             }
         }
 
@@ -3234,6 +3232,21 @@ export class Scene extends AbstractScene implements IAnimatable, IClipPlanesHold
     }
 
     /**
+     * Gets a post process using a given name (if many are found, this function will pick the first one)
+     * @param name defines the name to search for
+     * @return the found post process or null if not found at all.
+     */
+    public getPostProcessByName(name: string): Nullable<PostProcess> {
+        for (let postProcessIndex = 0; postProcessIndex < this.postProcesses.length; ++postProcessIndex) {
+            const postProcess = this.postProcesses[postProcessIndex];
+            if (postProcess.name === name) {
+                return postProcess;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Gets a boolean indicating if the given mesh is active
      * @param mesh defines the mesh to look for
      * @returns true if the mesh is in the active list

File diff suppressed because it is too large
+ 2 - 2
tests/es6Modules/webpack-stats.json


BIN
tests/validation/ReferenceImages/highlights.png