Просмотр исходного кода

Merge pull request #1 from BabylonJS/master

Update Fork to Upstream
ColorDigital-PS 6 лет назад
Родитель
Сommit
a22f48ac38
100 измененных файлов с 160288 добавлено и 149684 удалено
  1. 13 0
      .vscode/launch.json
  2. 291 28
      Playground/babylon.d.txt
  3. 1862 765
      Playground/babylonWebGPU.d.txt
  4. 1 1
      Playground/css/index.css
  5. 4 4
      Playground/debug.html
  6. 1 7
      Playground/indexStable.html
  7. 152204 147754
      Playground/js/babylonWebGpu.max.js
  8. 1 1
      Playground/js/babylonWebGpu.max.js.map
  9. 31 4
      Playground/js/config_versions.js
  10. 59 15
      Playground/js/main.js
  11. 60 16
      Playground/js/mainWebGPU.js
  12. 2 2
      Playground/js/menuPG.js
  13. 36 14
      Playground/js/settingsPG.js
  14. 3 0
      Playground/package.json
  15. 2 1
      Tools/Config/config.json
  16. 1 2
      dist/gui/readme.md
  17. 282 29
      dist/preview release/babylon.d.ts
  18. 2 2
      dist/preview release/babylon.js
  19. 1121 297
      dist/preview release/babylon.max.js
  20. 1 1
      dist/preview release/babylon.max.js.map
  21. 616 67
      dist/preview release/babylon.module.d.ts
  22. 295 29
      dist/preview release/documentation.d.ts
  23. 1 1
      dist/preview release/glTF2Interface/package.json
  24. 13 0
      dist/preview release/gui/babylon.gui.d.ts
  25. 125 41
      dist/preview release/gui/babylon.gui.js
  26. 1 1
      dist/preview release/gui/babylon.gui.js.map
  27. 1 1
      dist/preview release/gui/babylon.gui.min.js
  28. 26 0
      dist/preview release/gui/babylon.gui.module.d.ts
  29. 2 2
      dist/preview release/gui/package.json
  30. 1 1
      dist/preview release/gui/readme.md
  31. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js
  32. 16 4
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  33. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  34. 7 7
      dist/preview release/inspector/package.json
  35. 1 1
      dist/preview release/loaders/babylon.objFileLoader.js
  36. 1 1
      dist/preview release/loaders/babylon.objFileLoader.js.map
  37. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  38. 1 0
      dist/preview release/loaders/babylon.stlFileLoader.js
  39. 1 1
      dist/preview release/loaders/babylon.stlFileLoader.js.map
  40. 2 1
      dist/preview release/loaders/babylonjs.loaders.js
  41. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  42. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  43. 1 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  44. 3 3
      dist/preview release/loaders/package.json
  45. 11 4
      dist/preview release/materialsLibrary/babylon.gridMaterial.js
  46. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.js.map
  47. 1 1
      dist/preview release/materialsLibrary/babylon.gridMaterial.min.js
  48. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  49. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.js.map
  50. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  51. 12 5
      dist/preview release/materialsLibrary/babylonjs.materials.js
  52. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.js.map
  53. 1 1
      dist/preview release/materialsLibrary/babylonjs.materials.min.js
  54. 2 0
      dist/preview release/materialsLibrary/babylonjs.materials.module.d.ts
  55. 2 2
      dist/preview release/materialsLibrary/package.json
  56. 183 25
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  57. 7 7
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  58. 980 163
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  59. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  60. 396 52
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  61. 2 2
      dist/preview release/nodeEditor/package.json
  62. 1 1
      dist/preview release/package.json
  63. 1 1
      dist/preview release/packagesSizeBaseLine.json
  64. 2 2
      dist/preview release/postProcessesLibrary/package.json
  65. 2 2
      dist/preview release/proceduralTexturesLibrary/package.json
  66. 8 8
      dist/preview release/recast.js
  67. 3 3
      dist/preview release/serializers/package.json
  68. 616 67
      dist/preview release/viewer/babylon.module.d.ts
  69. 111 91
      dist/preview release/viewer/babylon.viewer.js
  70. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  71. 1 0
      dist/preview release/viewer/babylonjs.loaders.module.d.ts
  72. 5 1
      dist/preview release/what's new.md
  73. 88 0
      gui/src/2D/controls/image.ts
  74. 1 1
      gui/src/3D/gui3DManager.ts
  75. 17 1
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/nodeMaterialPropertyGridComponent.tsx
  76. 7 3
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx
  77. 1 1
      loaders/src/OBJ/objFileLoader.ts
  78. 2 0
      loaders/src/STL/stlFileLoader.ts
  79. 12 12
      localDev/lights.json
  80. 5 4
      materialsLibrary/src/grid/grid.vertex.fx
  81. 10 3
      materialsLibrary/src/grid/gridMaterial.ts
  82. 1 1
      materialsLibrary/src/water/water.fragment.fx
  83. 43 0
      nodeEditor/public/index-local.html
  84. 42 0
      nodeEditor/public/index.html
  85. 134 0
      nodeEditor/public/index.js
  86. 26 14
      nodeEditor/src/blockTools.ts
  87. 3 2
      nodeEditor/src/components/diagram/diagram.scss
  88. 8 1
      nodeEditor/src/components/diagram/generic/genericNodeModel.tsx
  89. 60 28
      nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx
  90. 11 11
      nodeEditor/src/components/diagram/input/inputNodeWidget.tsx
  91. 24 3
      nodeEditor/src/components/diagram/remap/remapNodeWidget.tsx
  92. 3 3
      nodeEditor/src/components/diagram/texture/textureNodeModel.tsx
  93. 115 4
      nodeEditor/src/components/diagram/texture/texturePropertyTabComponent.tsx
  94. 0 1
      nodeEditor/src/components/log/log.scss
  95. 1 1
      nodeEditor/src/components/nodeList/nodeList.scss
  96. 3 3
      nodeEditor/src/components/nodeList/nodeListComponent.tsx
  97. 54 0
      nodeEditor/src/components/preview/previewAreaComponent.tsx
  98. 139 30
      nodeEditor/src/components/preview/previewManager.ts
  99. 27 2
      nodeEditor/src/components/preview/previewMeshControlComponent.tsx
  100. 0 0
      nodeEditor/src/components/preview/previewMeshType.ts

+ 13 - 0
.vscode/launch.json

@@ -2,6 +2,19 @@
     "version": "2.0.0",
     "configurations": [
         {
+            "name": "Launch Node Material Editor (Chrome)",
+            "type": "chrome",
+            "request": "launch",
+            "url": "http://localhost:1338/nodeEditor/public/index-local.html",
+            "webRoot": "${workspaceRoot}/",
+            "sourceMaps": true,
+            "preLaunchTask": "run",
+            "userDataDir": "${workspaceRoot}/.tempChromeProfileForDebug",
+            "runtimeArgs": [
+                "--enable-unsafe-es3-apis"
+            ]
+        },        
+        {
             "name": "Launch Viewer (Chrome)",
             "type": "chrome",
             "request": "launch",

+ 291 - 28
Playground/babylon.d.txt

@@ -14391,7 +14391,7 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Reprasents a camera frustum
+     * Represents a camera frustum
      */
     export class Frustum {
         /**
@@ -15356,6 +15356,10 @@ declare module BABYLON {
      * @see http://doc.babylonjs.com/babylon101/materials#texture
      */
     export class Texture extends BaseTexture {
+        /**
+         * Gets or sets a general boolean used to indicate that textures containing direct data (buffers) must be saved as part of the serialization process
+         */
+        static SerializeBuffers: boolean;
         /** @hidden */
private static _CubeTextureParser: (jsonTexture: any, scene: Scene, rootUrl: string) => CubeTexture;
         /** @hidden */
private static _CreateMirror: (name: string, renderTargetSize: number, scene: Scene, generateMipMaps: boolean) => MirrorTexture;
         /** @hidden */
private static _CreateRenderTargetTexture: (name: string, renderTargetSize: number, scene: Scene, generateMipMaps: boolean) => RenderTargetTexture;
@@ -18571,9 +18575,10 @@ declare module BABYLON {
          * @param name Define the name of the material in the scene
          * @param scene Define the scene the material belongs to
          * @param shaderPath Defines  the route to the shader code in one of three ways:
-         *     - object - { vertex: "custom", fragment: "custom" }, used with Effect.ShadersStore["customVertexShader"] and Effect.ShadersStore["customFragmentShader"]
-         *     - object - { vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }, used with shader code in <script> tags
-         *     - string - "./COMMON_NAME", used with external files COMMON_NAME.vertex.fx and COMMON_NAME.fragment.fx in index.html folder.
+         *  * object: { vertex: "custom", fragment: "custom" }, used with Effect.ShadersStore["customVertexShader"] and Effect.ShadersStore["customFragmentShader"]
+         *  * object: { vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }, used with shader code in script tags
+         *  * object: { vertexSource: "vertex shader code string", fragmentSource: "fragment shader code string" } using with strings containing the shaders code
+         *  * string: "./COMMON_NAME", used with external files COMMON_NAME.vertex.fx and COMMON_NAME.fragment.fx in index.html folder.
          * @param options Define the options used to create the shader
          */
         constructor(name: string, scene: Scene, shaderPath: any, options?: Partial<IShaderMaterialOptions>);
@@ -21726,7 +21731,7 @@ declare module BABYLON {
      * @see http://doc.babylonjs.com/how_to/how_to_use_lod
      */
     export class MeshLODLevel {
-        /** Defines the distance where this level should star being displayed */
+        /** Defines the distance where this level should start being displayed */
         distance: number;
         /** Defines the mesh to use to render this level */
         mesh: Nullable<Mesh>;
@@ -21736,7 +21741,7 @@ declare module BABYLON {
          * @param mesh defines the mesh to use to render this level
          */
         constructor(
-        /** Defines the distance where this level should star being displayed */
+        /** Defines the distance where this level should start being displayed */
         distance: number, 
         /** Defines the mesh to use to render this level */
         mesh: Nullable<Mesh>);
@@ -24541,6 +24546,10 @@ declare module BABYLON {
          */
         getDirection(localAxis: Vector3): Vector3;
         /**
+         * Returns the current camera absolute rotation
+         */
+        readonly absoluteRotation: Quaternion;
+        /**
          * Gets the direction of the camera relative to a given local axis into a passed vector.
          * @param localAxis Defines the reference axis to provide a relative direction.
          * @param result Defines the vector to store the result in
@@ -27198,9 +27207,9 @@ declare module BABYLON {
          */
         gammaSpace: boolean;
         /**
-         * Gets whether or not the texture contains RGBD data.
+         * Gets or sets whether or not the texture contains RGBD data.
          */
-        readonly isRGBD: boolean;
+        isRGBD: boolean;
         /**
          * Is Z inverted in the texture (useful in a cube texture).
          */
@@ -36052,8 +36061,9 @@ declare module BABYLON {
         /**
          * Attaches the drag behavior the passed in mesh
          * @param ownerNode The mesh that will be dragged around once attached
+         * @param predicate Predicate to use for pick filtering
          */
-        attach(ownerNode: AbstractMesh): void;
+        attach(ownerNode: AbstractMesh, predicate?: (m: AbstractMesh) => boolean): void;
         /**
          * Force relase the drag action by code.
          */
@@ -40304,6 +40314,10 @@ declare module BABYLON {
          */
         updateGazeTrackerColor: boolean;
         /**
+         * If the controller laser color should be updated when selecting meshes
+         */
+        updateControllerLaserColor: boolean;
+        /**
          * The gaze tracking mesh corresponding to the left controller
          */
         readonly leftControllerGazeTrackerMesh: Nullable<Mesh>;
@@ -43455,7 +43469,11 @@ declare module BABYLON {
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
         private _getSamplingFilter;
-        createRenderTargetTexture(size: any, options: boolean | RenderTargetCreationOptions): InternalTexture;
+        private static _GetNativeTextureFormat;
+        createRenderTargetTexture(size: number | {
+            width: number;
+            height: number;
+        }, options: boolean | RenderTargetCreationOptions): InternalTexture;
         updateTextureSamplingMode(samplingMode: number, texture: InternalTexture): void;
         bindFramebuffer(texture: InternalTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number, forceFullscreenViewport?: boolean): void;
         unBindFramebuffer(texture: InternalTexture, disableGenerateMipMaps?: boolean, onBeforeUnbind?: () => void): void;
@@ -45075,6 +45093,10 @@ declare module BABYLON {
          */
         protected _mesh: Mesh;
         /**
+         * Gets the mesh used for the skybox.
+         */
+        readonly mesh: Mesh;
+        /**
          * The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
          * Also see the options.resolution property.
          */
@@ -45112,14 +45134,21 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Class used to host texture specific utilities
+     * Class used to host RGBD texture specific utilities
      */
-    export class BRDFTextureTools {
+    export class RGBDTextureTools {
         /**
-         * Expand the BRDF Texture from RGBD to Half Float if necessary.
+         * Expand the RGBD Texture from RGBD to Half Float if possible.
          * @param texture the texture to expand.
          */
-        private static _ExpandDefaultBRDFTexture;
+        static ExpandRGBDTexture(texture: Texture): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to host texture specific utilities
+     */
+    export class BRDFTextureTools {
         /**
          * Gets a default environment BRDF for MS-BRDF Height Correlated BRDF
          * @param scene defines the hosting scene
@@ -46081,6 +46110,7 @@ declare module BABYLON {
         LIGHTMAPDIRECTUV: number;
         USELIGHTMAPASSHADOWMAP: boolean;
         GAMMALIGHTMAP: boolean;
+        RGBDLIGHTMAP: boolean;
         REFLECTION: boolean;
         REFLECTIONMAP_3D: boolean;
         REFLECTIONMAP_SPHERICAL: boolean;
@@ -51291,9 +51321,9 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Enum used to define well known values e.g. values automatically provided by the system
+     * Enum used to define system values e.g. values automatically provided by the system
      */
-    export enum NodeMaterialWellKnownValues {
+    export enum NodeMaterialSystemValues {
         /** World */
         World = 1,
         /** View */
@@ -51435,6 +51465,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -51718,7 +51750,7 @@ declare module BABYLON {
         /**
          * Gets or sets the texture associated with the node
          */
-        texture: Nullable<BaseTexture>;
+        texture: Nullable<Texture>;
         /**
          * Create a new TextureBlock
          * @param name defines the block name
@@ -51895,6 +51927,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -51929,6 +51967,7 @@ declare module BABYLON {
         /** @hidden */
private _getFreeDefineName(prefix: string): string;
         /** @hidden */
private _excludeVariableName(name: string): void;
         /** @hidden */
private _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
+        /** @hidden */
private _emitExtension(name: string, extension: string): void;
         /** @hidden */
private _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
private _emitCodeFromInclude(includeName: string, comments: string, options?: {
             replaceStrings?: {
@@ -52200,7 +52239,13 @@ declare module BABYLON {
         private _valueCallback;
         private _type;
         private _animationType;
-        /** @hidden */
private _wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        /** Gets or set a value used to limit the range of float values */
+        min: number;
+        /** Gets or set a value used to limit the range of float values */
+        max: number;
+        /** Gets or sets a value used by the Node Material editor to determine how to configure the current value if it is a matrix */
+        matrixMode: number;
+        /** @hidden */
private _systemValue: Nullable<NodeMaterialSystemValues>;
         /** Gets or sets a boolean indicating that this input can be edited in the Inspector (false by default) */
         visibleInInspector: boolean;
         /**
@@ -52225,11 +52270,11 @@ declare module BABYLON {
          */
         setAsAttribute(attributeName?: string): InputBlock;
         /**
-         * Set the source of this connection point to a well known value
-         * @param value define the well known value to use (world, view, etc...) or null to switch to manual value
+         * Set the source of this connection point to a system value
+         * @param value define the system value to use (world, view, etc...) or null to switch to manual value
          * @returns the current connection point
          */
-        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): InputBlock;
+        setAsSystemValue(value: Nullable<NodeMaterialSystemValues>): InputBlock;
         /**
          * Gets or sets the value of that point.
          * Please note that this value will be ignored if valueCallback is defined
@@ -52268,13 +52313,13 @@ declare module BABYLON {
          */
         isVarying: boolean;
         /**
-         * Gets a boolean indicating that the current connection point is a well known value
+         * Gets a boolean indicating that the current connection point is a system value
          */
-        readonly isWellKnownValue: boolean;
+        readonly isSystemValue: boolean;
         /**
-         * Gets or sets the current well known value or null if not defined as well know value
+         * Gets or sets the current well known value or null if not defined as a system value
          */
-        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        systemValue: Nullable<NodeMaterialSystemValues>;
         /**
          * Gets the current class name
          * @returns the class name
@@ -52286,6 +52331,7 @@ declare module BABYLON {
          */
         animate(scene: Scene): void;
         private _emitDefine;
+        initialize(state: NodeMaterialBuildState): void;
         /**
          * Set the input block to its default value (based on its type)
          */
@@ -52657,6 +52703,58 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
private _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {
@@ -52957,6 +53055,22 @@ declare module BABYLON {
          */
         readonly input: NodeMaterialConnectionPoint;
         /**
+         * Gets the source min input component
+         */
+        readonly sourceMin: NodeMaterialConnectionPoint;
+        /**
+         * Gets the source max input component
+         */
+        readonly sourceMax: NodeMaterialConnectionPoint;
+        /**
+         * Gets the target min input component
+         */
+        readonly targetMin: NodeMaterialConnectionPoint;
+        /**
+         * Gets the target max input component
+         */
+        readonly targetMax: NodeMaterialConnectionPoint;
+        /**
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
@@ -53040,6 +53154,7 @@ declare module BABYLON {
          */
         readonly output: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
+        serialize(): any;
private _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -53360,11 +53475,11 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Block used to get the opposite of a value
+     * Block used to get the opposite (1 - x) of a value
      */
-    export class OppositeBlock extends NodeMaterialBlock {
+    export class OneMinusBlock extends NodeMaterialBlock {
         /**
-         * Creates a new OppositeBlock
+         * Creates a new OneMinusBlock
          * @param name defines the block name
          */
         constructor(name: string);
@@ -53516,6 +53631,88 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the distance between 2 values
+     */
+    export class DistanceBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new DistanceBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the left operand input component
+         */
+        readonly left: NodeMaterialConnectionPoint;
+        /**
+         * Gets the right operand input component
+         */
+        readonly right: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the length of a vector
+     */
+    export class LengthBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new LengthBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the value input component
+         */
+        readonly value: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get negative version of a value (i.e. x * -1)
+     */
+    export class NegateBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new NegateBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the value input component
+         */
+        readonly value: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {
@@ -53552,6 +53749,11 @@ declare module BABYLON {
          */
         setViewport(viewport?: Viewport): void;
         /**
+         * Binds the embedded attributes buffer to the effect.
+         * @param effect Defines the effect to bind the attributes for
+         */
+        bindBuffers(effect: Effect): void;
+        /**
          * Sets the current effect wrapper to use during draw.
          * The effect needs to be ready before calling this api.
          * This also sets the default full screen position attribute.
@@ -55302,6 +55504,18 @@ declare module BABYLON {
          */
         createCrowd(maxAgents: number, maxAgentRadius: number, scene: Scene): ICrowd;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -55353,6 +55567,18 @@ declare module BABYLON {
          */
         agentGoto(index: number, destination: Vector3): void;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -55525,6 +55751,18 @@ declare module BABYLON {
          */
         createCrowd(maxAgents: number, maxAgentRadius: number, scene: Scene): ICrowd;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Disposes
          */
         dispose(): void;
@@ -55614,6 +55852,18 @@ declare module BABYLON {
          */
         update(deltaTime: number): void;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -63104,6 +63354,10 @@ declare module BABYLON.GUI {
          */
         onImageLoadedObservable: BABYLON.Observable<Image>;
         /**
+         * BABYLON.Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
+         */
+        onSVGAttributesComputedObservable: BABYLON.Observable<Image>;
+        /**
          * Gets a boolean indicating that the content is loaded
          */
         readonly isLoaded: boolean;
@@ -63166,6 +63420,15 @@ declare module BABYLON.GUI {
          */
         source: BABYLON.Nullable<string>;
         /**
+         * Checks for svg document with icon id present
+         */
+        private _svgCheck;
+        /**
+         * Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
+         * given external svg file and icon id
+         */
+        private _getSVGAttribs;
+        /**
          * Gets or sets the cell width to use when animation sheet is enabled
          * @see http://doc.babylonjs.com/how_to/gui#image
          */

Разница между файлами не показана из-за своего большого размера
+ 1862 - 765
Playground/babylonWebGPU.d.txt


+ 1 - 1
Playground/css/index.css

@@ -682,7 +682,7 @@ body {
 .navbarBottom .links .link a {
     text-decoration: none;
     line-height: 35px;
-    padding: 6px 15px;
+    padding: 5px 15px;
     font-size: 16px;
     color: white;
 }

+ 4 - 4
Playground/debug.html

@@ -27,7 +27,6 @@
     <link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
     <link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
 
-    <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
     <meta name="msapplication-TileColor" content="#ffffff">
     <meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
     <meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
@@ -35,8 +34,7 @@
 
     <link rel="stylesheet" href="https://use.typekit.net/cta4xsb.css" />
     <link rel="stylesheet" href="css/index.css" />
-    <link rel="stylesheet" href="css/index710.css" />
-    <link rel="stylesheet" href="css/indexMobile.css" />
+    <link rel="stylesheet" href="css/index_mobile.css" />
 
     <!-- Pep -->
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
@@ -416,7 +414,9 @@
     </div>
 
     <!-- jQuery -->
-    <script src="https://code.jquery.com/jquery.js"></script>
+    <script src="js/libs/jquery.min.js"></script>
+    <script src="js/jquery.qrcode.js"></script>
+    <script src="js/qrcode.js"></script>
 
     <!-- Main scripts -->
     <script src="js/config_versions.js"></script>

+ 1 - 7
Playground/indexStable.html

@@ -1,11 +1,6 @@
 <!DOCTYPE html>
 <html>
 
-<!--
-    The purpose of the indexStable.html file is to ???
-    // TO DO - Complete that
- -->
-
 <head>
     <title>Babylon.js Playground</title>
     <meta charset='utf-8' />
@@ -14,8 +9,7 @@
 
     <link rel="stylesheet" href="https://use.typekit.net/cta4xsb.css" />
     <link rel="stylesheet" href="css/index.css" />
-    <link rel="stylesheet" href="css/index710.css" />
-    <link rel="stylesheet" href="css/indexMobile.css" />
+    <link rel="stylesheet" href="css/index_mobile.css" />
 
     <link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
     <meta name="msapplication-TileColor" content="#ffffff">

Разница между файлами не показана из-за своего большого размера
+ 152204 - 147754
Playground/js/babylonWebGpu.max.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
Playground/js/babylonWebGpu.max.js.map


+ 31 - 4
Playground/js/config_versions.js

@@ -1,6 +1,33 @@
 CONFIG_last_versions = [
-    ["Latest","https://preview.babylonjs.com/babylon.js"],
-    ["4.0.3","https://unpkg.com/babylonjs@4.0.3/babylon.js"],
-    ["4.0.0","https://unpkg.com/babylonjs@4.0.0/babylon.js"],
-    ["3.0","https://unpkg.com/babylonjs@3.0.7/dist/preview%20release/babylon.js"]
+    ["Latest",[
+        "https://preview.babylonjs.com/babylon.js",
+        "https://preview.babylonjs.com/gui/babylon.gui.min.js",
+        "https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js",
+        "https://preview.babylonjs.com/nodeEditor/babylon.nodeEditor.js",
+        "https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js",
+        "https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js",
+        "https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js",
+        "https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js",
+        "https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"
+    ]],
+    ["4.0.3", [
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/babylon.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/gui/babylon.gui.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/inspector/babylon.inspector.bundle.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/materialsLibrary/babylonjs.materials.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/postProcessesLibrary/babylonjs.postProcess.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/loaders/babylonjs.loaders.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@4.0.3/dist/serializers/babylonjs.serializers.min.js"
+    ]],
+    ["3.3", [
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/babylon.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/gui/babylon.gui.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/inspector/babylon.inspector.bundle.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/materialsLibrary/babylonjs.materials.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/postProcessesLibrary/babylonjs.postProcess.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/loaders/babylonjs.loaders.min.js",
+        "https://cdn.jsdelivr.net/gh/BabylonJS/Babylon.js@3.3.0/dist/serializers/babylonjs.serializers.min.js"
+    ]]
 ];

+ 59 - 15
Playground/js/main.js

@@ -5,7 +5,7 @@ var engine = null;
  */
 compileAndRun = function(parent, fpsLabel) {
     // If we need to change the version, don't do this
-    if (localStorage.getItem("bjs-playground-apiversion") && localStorage.getItem("bjs-playground-apiversion") != null) return;
+    if (parent.settingsPG.mustModifyBJSversion()) return;
 
     try {
         parent.menuPG.hideWaitDiv();
@@ -228,17 +228,19 @@ class Main {
         );
 
         // Restore BJS version if needed
+        var restoreVersionResult = true;
         if (this.parent.settingsPG.restoreVersion() == false) {
             // Check if there a hash in the URL
             this.checkHash();
+            restoreVersionResult = false;
         }
 
         // Load scripts list
-        this.loadScriptsList();
+        this.loadScriptsList(restoreVersionResult);
 
         // -------------------- UI --------------------
 
-        // Display BJS version - Need a check in case of version selection
+        // Display BJS version
         if (BABYLON) this.parent.utils.setToMultipleID("mainTitle", "innerHTML", "v" + BABYLON.Engine.Version);
         // Run
         this.parent.utils.setToMultipleID("runButton", "click", () => compileAndRun(this.parent, this.fpsLabel));
@@ -288,15 +290,52 @@ class Main {
         }
         // Language (JS / TS)
         this.parent.utils.setToMultipleID("toTSbutton", "click", function () {
-            if (this.parent.settingsPG.ScriptLanguage == "JS") {
+            if(location.hash != null && location.hash != ""){
                 this.parent.settingsPG.ScriptLanguage = "TS";
-                location.reload();
+                window.location = "./";
+            }else{
+                if (this.parent.settingsPG.ScriptLanguage == "JS") {
+                    //revert in case the reload is cancel due to safe mode
+                    if(document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()).classList.contains('checked')){
+                        // Message before unload
+                        var languageTSswapper =  function () {
+                            this.parent.settingsPG.ScriptLanguage = "TS";
+                            window.removeEventListener('unload', languageTSswapper.bind(this));
+                        };
+                        window.addEventListener('unload',languageTSswapper.bind(this));
+                        
+                        location.reload();
+                    }
+                    else {
+                        this.parent.settingsPG.ScriptLanguage = "TS";
+                        location.reload();
+                    }
+                }
             }
+           
         }.bind(this));
         this.parent.utils.setToMultipleID("toJSbutton", "click", function () {
-            if (this.parent.settingsPG.ScriptLanguage == "TS") {
+            if(location.hash != null && location.hash != ""){
                 this.parent.settingsPG.ScriptLanguage = "JS";
-                location.reload();
+                window.location = "./";
+            }else{
+                if (this.parent.settingsPG.ScriptLanguage == "TS") {
+                    //revert in case the reload is cancel due to safe mode
+                    if(document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()).classList.contains('checked')){
+                        // Message before unload
+                        var LanguageJSswapper =  function () {
+                            this.parent.settingsPG.ScriptLanguage = "JS";
+                            window.removeEventListener('unload', LanguageJSswapper.bind(this));
+                        };
+                        window.addEventListener('unload',LanguageJSswapper.bind(this));
+                        
+                        location.reload();
+                    }
+                    else {
+                        this.parent.settingsPG.ScriptLanguage = "JS";
+                        location.reload();
+                    }
+                }
             }
         }.bind(this));
         // Safe mode
@@ -405,11 +444,11 @@ class Main {
     /**
      * Load the examples scripts list in the database
      */
-    loadScriptsList() {
+    loadScriptsList(restoreVersionResult) {
         var exampleList = document.getElementById("exampleList");
 
         var xhr = new XMLHttpRequest();
-        //Open Typescript or Javascript examples
+        // Open Typescript or Javascript examples
         if (exampleList.className != 'typescript') {
             xhr.open('GET', 'https://raw.githubusercontent.com/BabylonJS/Documentation/master/examples/list.json', true);
         }
@@ -473,6 +512,10 @@ class Main {
                                 examplePGLink.classList.add("itemLinePGLink");
                                 examplePGLink.innerText = "Display";
                                 examplePGLink.href = this.scripts[i].samples[ii].PGID;
+                                examplePGLink.addEventListener("click", function() {
+                                    location.href = this.href;
+                                    location.reload();
+                                });
 
                                 exampleContentLink.appendChild(exampleTitle);
                                 exampleContentLink.appendChild(exampleDescr);
@@ -497,7 +540,7 @@ class Main {
                         exampleList.appendChild(noResultContainer);
                     }
 
-                    if (!location.hash) {
+                    if (!location.hash && restoreVersionResult == false) {
                         // Query string
                         var queryString = window.location.search;
 
@@ -554,8 +597,6 @@ class Main {
                         }
                     }
 
-                    // Restore theme
-                    this.parent.settingsPG.restoreTheme(this.parent.monacoCreator);
                     // Restore language
                     this.parent.settingsPG.setScriptLanguage();
                 }
@@ -594,9 +635,13 @@ class Main {
         this.parent.monacoCreator.JsEditor.focus();
     };
 
+    compileAndRunFromOutside() {
+        compileAndRun(this.parent, this.fpsLabel);
+    };
+
     checkSafeMode(message) {
-        if (document.getElementById("safemodeToggle" + this.parent.getCurrentSize) &&
-            document.getElementById("safemodeToggle" + this.parent.getCurrentSize).classList.contains('checked')) {
+        if (document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()) &&
+            document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()).classList.contains('checked')) {
             let confirm = window.confirm(message);
             if (!confirm) {
                 return false;
@@ -647,7 +692,6 @@ class Main {
         document.getElementById("saveFormDescription").readOnly = true;
         document.getElementById("saveFormTags").readOnly = true;
         document.getElementById("saveFormButtonOk").style.display = "none";
-        this.parent.utils.setToMultipleID("metadataButton", "display", "inline-block");
     };
 
     /*

+ 60 - 16
Playground/js/mainWebGPU.js

@@ -5,7 +5,7 @@ var engine = null;
  */
 compileAndRun = function(parent, fpsLabel) {
     // If we need to change the version, don't do this
-    if (localStorage.getItem("bjs-playground-apiversion") && localStorage.getItem("bjs-playground-apiversion") != null) return;
+    if (parent.settingsPG.mustModifyBJSversion()) return;
 
     try {
         parent.menuPG.hideWaitDiv();
@@ -251,17 +251,19 @@ class Main {
         );
 
         // Restore BJS version if needed
+        var restoreVersionResult = true;
         if (this.parent.settingsPG.restoreVersion() == false) {
             // Check if there a hash in the URL
             this.checkHash();
+            restoreVersionResult = false;
         }
 
         // Load scripts list
-        this.loadScriptsList();
+        this.loadScriptsList(restoreVersionResult);
 
         // -------------------- UI --------------------
 
-        // Display BJS version - Need a check in case of version selection
+        // Display BJS version
         if (BABYLON) this.parent.utils.setToMultipleID("mainTitle", "innerHTML", "v" + BABYLON.Engine.Version);
         // Run
         this.parent.utils.setToMultipleID("runButton", "click", () => compileAndRun(this.parent, this.fpsLabel));
@@ -311,15 +313,52 @@ class Main {
         }
         // Language (JS / TS)
         this.parent.utils.setToMultipleID("toTSbutton", "click", function () {
-            if (this.parent.settingsPG.ScriptLanguage == "JS") {
+            if(location.hash != null && location.hash != ""){
                 this.parent.settingsPG.ScriptLanguage = "TS";
-                location.reload();
+                window.location = "./";
+            }else{
+                if (this.parent.settingsPG.ScriptLanguage == "JS") {
+                    //revert in case the reload is cancel due to safe mode
+                    if(document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()).classList.contains('checked')){
+                        // Message before unload
+                        var languageTSswapper =  function () {
+                            this.parent.settingsPG.ScriptLanguage = "TS";
+                            window.removeEventListener('unload', languageTSswapper.bind(this));
+                        };
+                        window.addEventListener('unload',languageTSswapper.bind(this));
+                        
+                        location.reload();
+                    }
+                    else {
+                        this.parent.settingsPG.ScriptLanguage = "TS";
+                        location.reload();
+                    }
+                }
             }
+           
         }.bind(this));
         this.parent.utils.setToMultipleID("toJSbutton", "click", function () {
-            if (this.parent.settingsPG.ScriptLanguage == "TS") {
+            if(location.hash != null && location.hash != ""){
                 this.parent.settingsPG.ScriptLanguage = "JS";
-                location.reload();
+                window.location = "./";
+            }else{
+                if (this.parent.settingsPG.ScriptLanguage == "TS") {
+                    //revert in case the reload is cancel due to safe mode
+                    if(document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()).classList.contains('checked')){
+                        // Message before unload
+                        var LanguageJSswapper =  function () {
+                            this.parent.settingsPG.ScriptLanguage = "JS";
+                            window.removeEventListener('unload', LanguageJSswapper.bind(this));
+                        };
+                        window.addEventListener('unload',LanguageJSswapper.bind(this));
+                        
+                        location.reload();
+                    }
+                    else {
+                        this.parent.settingsPG.ScriptLanguage = "JS";
+                        location.reload();
+                    }
+                }
             }
         }.bind(this));
         // Safe mode
@@ -428,11 +467,11 @@ class Main {
     /**
      * Load the examples scripts list in the database
      */
-    loadScriptsList() {
+    loadScriptsList(restoreVersionResult) {
         var exampleList = document.getElementById("exampleList");
 
         var xhr = new XMLHttpRequest();
-        //Open Typescript or Javascript examples
+        // Open Typescript or Javascript examples
         if (exampleList.className != 'typescript') {
             xhr.open('GET', 'https://raw.githubusercontent.com/BabylonJS/Documentation/master/examples/list.json', true);
         }
@@ -496,6 +535,10 @@ class Main {
                                 examplePGLink.classList.add("itemLinePGLink");
                                 examplePGLink.innerText = "Display";
                                 examplePGLink.href = this.scripts[i].samples[ii].PGID;
+                                examplePGLink.addEventListener("click", function() {
+                                    location.href = this.href;
+                                    location.reload();
+                                });
 
                                 exampleContentLink.appendChild(exampleTitle);
                                 exampleContentLink.appendChild(exampleDescr);
@@ -520,7 +563,7 @@ class Main {
                         exampleList.appendChild(noResultContainer);
                     }
 
-                    if (!location.hash) {
+                    if (!location.hash && restoreVersionResult == false) {
                         // Query string
                         var queryString = window.location.search;
 
@@ -577,8 +620,6 @@ class Main {
                         }
                     }
 
-                    // Restore theme
-                    this.parent.settingsPG.restoreTheme(this.parent.monacoCreator);
                     // Restore language
                     this.parent.settingsPG.setScriptLanguage();
                 }
@@ -617,9 +658,13 @@ class Main {
         this.parent.monacoCreator.JsEditor.focus();
     };
 
+    compileAndRunFromOutside() {
+        compileAndRun(this.parent, this.fpsLabel);
+    };
+
     checkSafeMode(message) {
-        if (document.getElementById("safemodeToggle" + this.parent.getCurrentSize) &&
-            document.getElementById("safemodeToggle" + this.parent.getCurrentSize).classList.contains('checked')) {
+        if (document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()) &&
+            document.getElementById("safemodeToggle" + this.parent.utils.getCurrentSize()).classList.contains('checked')) {
             let confirm = window.confirm(message);
             if (!confirm) {
                 return false;
@@ -670,7 +715,6 @@ class Main {
         document.getElementById("saveFormDescription").readOnly = true;
         document.getElementById("saveFormTags").readOnly = true;
         document.getElementById("saveFormButtonOk").style.display = "none";
-        this.parent.utils.setToMultipleID("metadataButton", "display", "inline-block");
     };
 
     /*
@@ -857,4 +901,4 @@ class Main {
         }
         setTimeout(this.checkHash.bind(this), 200);
     };
-}
+}

+ 2 - 2
Playground/js/menuPG.js

@@ -86,7 +86,7 @@ class MenuPG {
 
         // Message before unload
         window.addEventListener('beforeunload', function () {
-            if (localStorage.getItem("bjs-playground-apiversion") && localStorage.getItem("bjs-playground-apiversion") != null) return;
+            if (this.parent.settingsPG.mustModifyBJSversion()) return;
             this.exitPrompt();
         }.bind(this));
 
@@ -130,7 +130,7 @@ class MenuPG {
                 newButton.classList.add("option");
                 if(CONFIG_last_versions[j][0] == "Latest") newButton.innerText = "Latest";
                 else newButton.innerText = "v" + CONFIG_last_versions[j][0];
-                newButton.value = CONFIG_last_versions[j][1];
+                newButton.value = CONFIG_last_versions[j][0];
 
                 newButton.addEventListener("click", function (evt) {
                     this.parent.settingsPG.setBJSversion(evt, this.parent.monacoCreator.getCode());

+ 36 - 14
Playground/js/settingsPG.js

@@ -148,26 +148,48 @@ class SettingsPG {
      * Check if we need to restore a BJS version
      */
     restoreVersion() {
-        if (localStorage.getItem("bjs-playground-apiversion") && localStorage.getItem("bjs-playground-apiversion") != null) {
+        if (this.mustModifyBJSversion()) {
+            this.parent.menuPG.displayWaitDiv();
+
+            var apiVersion = localStorage.getItem("bjs-playground-apiversion");
             BABYLON = null;
 
-            this.parent.menuPG.displayWaitDiv();
+            var position = 0;
+            for (var i = 0; i < CONFIG_last_versions.length; i++) {
+                if (CONFIG_last_versions[i][0] == apiVersion) {
+                    position = i;
+                    break;
+                }
+            }
+
+            var count = CONFIG_last_versions[position][1].length;
+            for (var i = 0; i < CONFIG_last_versions[position][1].length; i++) {
+                var newBJSscript = document.createElement('script');
+                newBJSscript.src = CONFIG_last_versions[position][1][i];
+                newBJSscript.onload = function () {
+                    count--;
+                    if (count == 0) {
+                        if (BABYLON.Engine.Version.search('-') != -1) this.parent.menuPG.displayVersionNumber("Latest");
+                        else this.parent.menuPG.displayVersionNumber(BABYLON.Engine.Version);
+                        this.parent.utils.setToMultipleID("mainTitle", "innerHTML", "v" + BABYLON.Engine.Version);
 
-            var newBJSscript = document.createElement('script');
-            newBJSscript.src = localStorage.getItem("bjs-playground-apiversion");
-            newBJSscript.onload = function () {
-                if(BABYLON.Engine.Version.search('-') != -1) this.parent.menuPG.displayVersionNumber("Latest");
-                else this.parent.menuPG.displayVersionNumber(BABYLON.Engine.Version);
-                this.parent.monacoCreator.setCode(localStorage.getItem("bjs-playground-apiversion-tempcode"));
+                        this.parent.monacoCreator.setCode(localStorage.getItem("bjs-playground-apiversion-tempcode"));
 
-                localStorage.removeItem("bjs-playground-apiversion");
-                localStorage.removeItem("bjs-playground-apiversion-tempcode");
+                        localStorage.removeItem("bjs-playground-apiversion");
+                        localStorage.removeItem("bjs-playground-apiversion-tempcode");
 
-                this.parent.main.compileAndRun();
-            }.bind(this);
+                        this.parent.main.compileAndRunFromOutside();
+                    }
+                }.bind(this);
 
-            document.head.appendChild(newBJSscript);
+                document.head.appendChild(newBJSscript);
+            }
         }
         else return false;
     };
-};
+
+    mustModifyBJSversion() {
+        if (localStorage.getItem("bjs-playground-apiversion") && localStorage.getItem("bjs-playground-apiversion") != null && localStorage.getItem("bjs-playground-apiversion") != "Latest") return true;
+        else return false;
+    };
+};

+ 3 - 0
Playground/package.json

@@ -13,5 +13,8 @@
   },
   "scripts": {
     "test": "browser-sync start --server --files **/* --no-inject-changes --startPath index.html"
+  },
+  "dependencies": {
+    "npm": "^6.11.2"
   }
 }

+ 2 - 1
Tools/Config/config.json

@@ -600,7 +600,8 @@
                 "react-dom",
                 "dagre",
                 "re-resizable",
-                "glTF"
+                "glTF",
+                "file-saver"
             ],
             "umd": {
                 "packageName": "babylonjs-node-editor",

+ 1 - 2
dist/gui/readme.md

@@ -26,8 +26,7 @@ If using TypeScript, the typing needs to be added to tsconfig.json:
     ....
     "types": [
         "babylonjs",
-        "babylonjs-gui",
-        "angularFTW"
+        "babylonjs-gui"
     ],
     ....
 ```

+ 282 - 29
dist/preview release/babylon.d.ts

@@ -14553,7 +14553,7 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Reprasents a camera frustum
+     * Represents a camera frustum
      */
     export class Frustum {
         /**
@@ -15551,6 +15551,10 @@ declare module BABYLON {
      * @see http://doc.babylonjs.com/babylon101/materials#texture
      */
     export class Texture extends BaseTexture {
+        /**
+         * Gets or sets a general boolean used to indicate that textures containing direct data (buffers) must be saved as part of the serialization process
+         */
+        static SerializeBuffers: boolean;
         /** @hidden */
         static _CubeTextureParser: (jsonTexture: any, scene: Scene, rootUrl: string) => CubeTexture;
         /** @hidden */
@@ -18832,9 +18836,10 @@ declare module BABYLON {
          * @param name Define the name of the material in the scene
          * @param scene Define the scene the material belongs to
          * @param shaderPath Defines  the route to the shader code in one of three ways:
-         *     - object - { vertex: "custom", fragment: "custom" }, used with Effect.ShadersStore["customVertexShader"] and Effect.ShadersStore["customFragmentShader"]
-         *     - object - { vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }, used with shader code in <script> tags
-         *     - string - "./COMMON_NAME", used with external files COMMON_NAME.vertex.fx and COMMON_NAME.fragment.fx in index.html folder.
+         *  * object: { vertex: "custom", fragment: "custom" }, used with Effect.ShadersStore["customVertexShader"] and Effect.ShadersStore["customFragmentShader"]
+         *  * object: { vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }, used with shader code in script tags
+         *  * object: { vertexSource: "vertex shader code string", fragmentSource: "fragment shader code string" } using with strings containing the shaders code
+         *  * string: "./COMMON_NAME", used with external files COMMON_NAME.vertex.fx and COMMON_NAME.fragment.fx in index.html folder.
          * @param options Define the options used to create the shader
          */
         constructor(name: string, scene: Scene, shaderPath: any, options?: Partial<IShaderMaterialOptions>);
@@ -22032,7 +22037,7 @@ declare module BABYLON {
      * @see http://doc.babylonjs.com/how_to/how_to_use_lod
      */
     export class MeshLODLevel {
-        /** Defines the distance where this level should star being displayed */
+        /** Defines the distance where this level should start being displayed */
         distance: number;
         /** Defines the mesh to use to render this level */
         mesh: Nullable<Mesh>;
@@ -22042,7 +22047,7 @@ declare module BABYLON {
          * @param mesh defines the mesh to use to render this level
          */
         constructor(
-        /** Defines the distance where this level should star being displayed */
+        /** Defines the distance where this level should start being displayed */
         distance: number, 
         /** Defines the mesh to use to render this level */
         mesh: Nullable<Mesh>);
@@ -24922,6 +24927,10 @@ declare module BABYLON {
          */
         getDirection(localAxis: Vector3): Vector3;
         /**
+         * Returns the current camera absolute rotation
+         */
+        readonly absoluteRotation: Quaternion;
+        /**
          * Gets the direction of the camera relative to a given local axis into a passed vector.
          * @param localAxis Defines the reference axis to provide a relative direction.
          * @param result Defines the vector to store the result in
@@ -27688,9 +27697,9 @@ declare module BABYLON {
          */
         gammaSpace: boolean;
         /**
-         * Gets whether or not the texture contains RGBD data.
+         * Gets or sets whether or not the texture contains RGBD data.
          */
-        readonly isRGBD: boolean;
+        isRGBD: boolean;
         /**
          * Is Z inverted in the texture (useful in a cube texture).
          */
@@ -36751,8 +36760,9 @@ declare module BABYLON {
         /**
          * Attaches the drag behavior the passed in mesh
          * @param ownerNode The mesh that will be dragged around once attached
+         * @param predicate Predicate to use for pick filtering
          */
-        attach(ownerNode: AbstractMesh): void;
+        attach(ownerNode: AbstractMesh, predicate?: (m: AbstractMesh) => boolean): void;
         /**
          * Force relase the drag action by code.
          */
@@ -41022,6 +41032,10 @@ declare module BABYLON {
          */
         updateGazeTrackerColor: boolean;
         /**
+         * If the controller laser color should be updated when selecting meshes
+         */
+        updateControllerLaserColor: boolean;
+        /**
          * The gaze tracking mesh corresponding to the left controller
          */
         readonly leftControllerGazeTrackerMesh: Nullable<Mesh>;
@@ -44213,7 +44227,11 @@ declare module BABYLON {
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
         private _getSamplingFilter;
-        createRenderTargetTexture(size: any, options: boolean | RenderTargetCreationOptions): InternalTexture;
+        private static _GetNativeTextureFormat;
+        createRenderTargetTexture(size: number | {
+            width: number;
+            height: number;
+        }, options: boolean | RenderTargetCreationOptions): InternalTexture;
         updateTextureSamplingMode(samplingMode: number, texture: InternalTexture): void;
         bindFramebuffer(texture: InternalTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number, forceFullscreenViewport?: boolean): void;
         unBindFramebuffer(texture: InternalTexture, disableGenerateMipMaps?: boolean, onBeforeUnbind?: () => void): void;
@@ -45839,6 +45857,10 @@ declare module BABYLON {
          */
         protected _mesh: Mesh;
         /**
+         * Gets the mesh used for the skybox.
+         */
+        readonly mesh: Mesh;
+        /**
          * The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
          * Also see the options.resolution property.
          */
@@ -45876,14 +45898,21 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Class used to host texture specific utilities
+     * Class used to host RGBD texture specific utilities
      */
-    export class BRDFTextureTools {
+    export class RGBDTextureTools {
         /**
-         * Expand the BRDF Texture from RGBD to Half Float if necessary.
+         * Expand the RGBD Texture from RGBD to Half Float if possible.
          * @param texture the texture to expand.
          */
-        private static _ExpandDefaultBRDFTexture;
+        static ExpandRGBDTexture(texture: Texture): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to host texture specific utilities
+     */
+    export class BRDFTextureTools {
         /**
          * Gets a default environment BRDF for MS-BRDF Height Correlated BRDF
          * @param scene defines the hosting scene
@@ -46856,6 +46885,7 @@ declare module BABYLON {
         LIGHTMAPDIRECTUV: number;
         USELIGHTMAPASSHADOWMAP: boolean;
         GAMMALIGHTMAP: boolean;
+        RGBDLIGHTMAP: boolean;
         REFLECTION: boolean;
         REFLECTIONMAP_3D: boolean;
         REFLECTIONMAP_SPHERICAL: boolean;
@@ -52082,9 +52112,9 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Enum used to define well known values e.g. values automatically provided by the system
+     * Enum used to define system values e.g. values automatically provided by the system
      */
-    export enum NodeMaterialWellKnownValues {
+    export enum NodeMaterialSystemValues {
         /** World */
         World = 1,
         /** View */
@@ -52227,6 +52257,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -52512,7 +52544,7 @@ declare module BABYLON {
         /**
          * Gets or sets the texture associated with the node
          */
-        texture: Nullable<BaseTexture>;
+        texture: Nullable<Texture>;
         /**
          * Create a new TextureBlock
          * @param name defines the block name
@@ -52690,6 +52722,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -52736,6 +52774,8 @@ declare module BABYLON {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -53018,8 +53058,14 @@ declare module BABYLON {
         private _valueCallback;
         private _type;
         private _animationType;
-        /** @hidden */
-        _wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        /** Gets or set a value used to limit the range of float values */
+        min: number;
+        /** Gets or set a value used to limit the range of float values */
+        max: number;
+        /** Gets or sets a value used by the Node Material editor to determine how to configure the current value if it is a matrix */
+        matrixMode: number;
+        /** @hidden */
+        _systemValue: Nullable<NodeMaterialSystemValues>;
         /** Gets or sets a boolean indicating that this input can be edited in the Inspector (false by default) */
         visibleInInspector: boolean;
         /**
@@ -53044,11 +53090,11 @@ declare module BABYLON {
          */
         setAsAttribute(attributeName?: string): InputBlock;
         /**
-         * Set the source of this connection point to a well known value
-         * @param value define the well known value to use (world, view, etc...) or null to switch to manual value
+         * Set the source of this connection point to a system value
+         * @param value define the system value to use (world, view, etc...) or null to switch to manual value
          * @returns the current connection point
          */
-        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): InputBlock;
+        setAsSystemValue(value: Nullable<NodeMaterialSystemValues>): InputBlock;
         /**
          * Gets or sets the value of that point.
          * Please note that this value will be ignored if valueCallback is defined
@@ -53087,13 +53133,13 @@ declare module BABYLON {
          */
         isVarying: boolean;
         /**
-         * Gets a boolean indicating that the current connection point is a well known value
+         * Gets a boolean indicating that the current connection point is a system value
          */
-        readonly isWellKnownValue: boolean;
+        readonly isSystemValue: boolean;
         /**
-         * Gets or sets the current well known value or null if not defined as well know value
+         * Gets or sets the current well known value or null if not defined as a system value
          */
-        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        systemValue: Nullable<NodeMaterialSystemValues>;
         /**
          * Gets the current class name
          * @returns the class name
@@ -53105,6 +53151,7 @@ declare module BABYLON {
          */
         animate(scene: Scene): void;
         private _emitDefine;
+        initialize(state: NodeMaterialBuildState): void;
         /**
          * Set the input block to its default value (based on its type)
          */
@@ -53486,6 +53533,59 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {
@@ -53788,6 +53888,22 @@ declare module BABYLON {
          */
         readonly input: NodeMaterialConnectionPoint;
         /**
+         * Gets the source min input component
+         */
+        readonly sourceMin: NodeMaterialConnectionPoint;
+        /**
+         * Gets the source max input component
+         */
+        readonly sourceMax: NodeMaterialConnectionPoint;
+        /**
+         * Gets the target min input component
+         */
+        readonly targetMin: NodeMaterialConnectionPoint;
+        /**
+         * Gets the target max input component
+         */
+        readonly targetMax: NodeMaterialConnectionPoint;
+        /**
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
@@ -53872,6 +53988,8 @@ declare module BABYLON {
          */
         readonly output: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -54192,11 +54310,11 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Block used to get the opposite of a value
+     * Block used to get the opposite (1 - x) of a value
      */
-    export class OppositeBlock extends NodeMaterialBlock {
+    export class OneMinusBlock extends NodeMaterialBlock {
         /**
-         * Creates a new OppositeBlock
+         * Creates a new OneMinusBlock
          * @param name defines the block name
          */
         constructor(name: string);
@@ -54348,6 +54466,88 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the distance between 2 values
+     */
+    export class DistanceBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new DistanceBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the left operand input component
+         */
+        readonly left: NodeMaterialConnectionPoint;
+        /**
+         * Gets the right operand input component
+         */
+        readonly right: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the length of a vector
+     */
+    export class LengthBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new LengthBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the value input component
+         */
+        readonly value: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get negative version of a value (i.e. x * -1)
+     */
+    export class NegateBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new NegateBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the value input component
+         */
+        readonly value: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {
@@ -54384,6 +54584,11 @@ declare module BABYLON {
          */
         setViewport(viewport?: Viewport): void;
         /**
+         * Binds the embedded attributes buffer to the effect.
+         * @param effect Defines the effect to bind the attributes for
+         */
+        bindBuffers(effect: Effect): void;
+        /**
          * Sets the current effect wrapper to use during draw.
          * The effect needs to be ready before calling this api.
          * This also sets the default full screen position attribute.
@@ -56135,6 +56340,18 @@ declare module BABYLON {
          */
         createCrowd(maxAgents: number, maxAgentRadius: number, scene: Scene): ICrowd;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -56186,6 +56403,18 @@ declare module BABYLON {
          */
         agentGoto(index: number, destination: Vector3): void;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -56358,6 +56587,18 @@ declare module BABYLON {
          */
         createCrowd(maxAgents: number, maxAgentRadius: number, scene: Scene): ICrowd;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Disposes
          */
         dispose(): void;
@@ -56447,6 +56688,18 @@ declare module BABYLON {
          */
         update(deltaTime: number): void;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/babylon.js


Разница между файлами не показана из-за своего большого размера
+ 1121 - 297
dist/preview release/babylon.max.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/babylon.max.js.map


Разница между файлами не показана из-за своего большого размера
+ 616 - 67
dist/preview release/babylon.module.d.ts


+ 295 - 29
dist/preview release/documentation.d.ts

@@ -14553,7 +14553,7 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Reprasents a camera frustum
+     * Represents a camera frustum
      */
     export class Frustum {
         /**
@@ -15551,6 +15551,10 @@ declare module BABYLON {
      * @see http://doc.babylonjs.com/babylon101/materials#texture
      */
     export class Texture extends BaseTexture {
+        /**
+         * Gets or sets a general boolean used to indicate that textures containing direct data (buffers) must be saved as part of the serialization process
+         */
+        static SerializeBuffers: boolean;
         /** @hidden */
         static _CubeTextureParser: (jsonTexture: any, scene: Scene, rootUrl: string) => CubeTexture;
         /** @hidden */
@@ -18832,9 +18836,10 @@ declare module BABYLON {
          * @param name Define the name of the material in the scene
          * @param scene Define the scene the material belongs to
          * @param shaderPath Defines  the route to the shader code in one of three ways:
-         *     - object - { vertex: "custom", fragment: "custom" }, used with Effect.ShadersStore["customVertexShader"] and Effect.ShadersStore["customFragmentShader"]
-         *     - object - { vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }, used with shader code in <script> tags
-         *     - string - "./COMMON_NAME", used with external files COMMON_NAME.vertex.fx and COMMON_NAME.fragment.fx in index.html folder.
+         *  * object: { vertex: "custom", fragment: "custom" }, used with Effect.ShadersStore["customVertexShader"] and Effect.ShadersStore["customFragmentShader"]
+         *  * object: { vertexElement: "vertexShaderCode", fragmentElement: "fragmentShaderCode" }, used with shader code in script tags
+         *  * object: { vertexSource: "vertex shader code string", fragmentSource: "fragment shader code string" } using with strings containing the shaders code
+         *  * string: "./COMMON_NAME", used with external files COMMON_NAME.vertex.fx and COMMON_NAME.fragment.fx in index.html folder.
          * @param options Define the options used to create the shader
          */
         constructor(name: string, scene: Scene, shaderPath: any, options?: Partial<IShaderMaterialOptions>);
@@ -22032,7 +22037,7 @@ declare module BABYLON {
      * @see http://doc.babylonjs.com/how_to/how_to_use_lod
      */
     export class MeshLODLevel {
-        /** Defines the distance where this level should star being displayed */
+        /** Defines the distance where this level should start being displayed */
         distance: number;
         /** Defines the mesh to use to render this level */
         mesh: Nullable<Mesh>;
@@ -22042,7 +22047,7 @@ declare module BABYLON {
          * @param mesh defines the mesh to use to render this level
          */
         constructor(
-        /** Defines the distance where this level should star being displayed */
+        /** Defines the distance where this level should start being displayed */
         distance: number, 
         /** Defines the mesh to use to render this level */
         mesh: Nullable<Mesh>);
@@ -24922,6 +24927,10 @@ declare module BABYLON {
          */
         getDirection(localAxis: Vector3): Vector3;
         /**
+         * Returns the current camera absolute rotation
+         */
+        readonly absoluteRotation: Quaternion;
+        /**
          * Gets the direction of the camera relative to a given local axis into a passed vector.
          * @param localAxis Defines the reference axis to provide a relative direction.
          * @param result Defines the vector to store the result in
@@ -27688,9 +27697,9 @@ declare module BABYLON {
          */
         gammaSpace: boolean;
         /**
-         * Gets whether or not the texture contains RGBD data.
+         * Gets or sets whether or not the texture contains RGBD data.
          */
-        readonly isRGBD: boolean;
+        isRGBD: boolean;
         /**
          * Is Z inverted in the texture (useful in a cube texture).
          */
@@ -36751,8 +36760,9 @@ declare module BABYLON {
         /**
          * Attaches the drag behavior the passed in mesh
          * @param ownerNode The mesh that will be dragged around once attached
+         * @param predicate Predicate to use for pick filtering
          */
-        attach(ownerNode: AbstractMesh): void;
+        attach(ownerNode: AbstractMesh, predicate?: (m: AbstractMesh) => boolean): void;
         /**
          * Force relase the drag action by code.
          */
@@ -41022,6 +41032,10 @@ declare module BABYLON {
          */
         updateGazeTrackerColor: boolean;
         /**
+         * If the controller laser color should be updated when selecting meshes
+         */
+        updateControllerLaserColor: boolean;
+        /**
          * The gaze tracking mesh corresponding to the left controller
          */
         readonly leftControllerGazeTrackerMesh: Nullable<Mesh>;
@@ -44213,7 +44227,11 @@ declare module BABYLON {
          */
         createCubeTexture(rootUrl: string, scene: Nullable<Scene>, files: Nullable<string[]>, noMipmap?: boolean, onLoad?: Nullable<(data?: any) => void>, onError?: Nullable<(message?: string, exception?: any) => void>, format?: number, forcedExtension?: any, createPolynomials?: boolean, lodScale?: number, lodOffset?: number, fallback?: Nullable<InternalTexture>): InternalTexture;
         private _getSamplingFilter;
-        createRenderTargetTexture(size: any, options: boolean | RenderTargetCreationOptions): InternalTexture;
+        private static _GetNativeTextureFormat;
+        createRenderTargetTexture(size: number | {
+            width: number;
+            height: number;
+        }, options: boolean | RenderTargetCreationOptions): InternalTexture;
         updateTextureSamplingMode(samplingMode: number, texture: InternalTexture): void;
         bindFramebuffer(texture: InternalTexture, faceIndex?: number, requiredWidth?: number, requiredHeight?: number, forceFullscreenViewport?: boolean): void;
         unBindFramebuffer(texture: InternalTexture, disableGenerateMipMaps?: boolean, onBeforeUnbind?: () => void): void;
@@ -45839,6 +45857,10 @@ declare module BABYLON {
          */
         protected _mesh: Mesh;
         /**
+         * Gets the mesh used for the skybox.
+         */
+        readonly mesh: Mesh;
+        /**
          * The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
          * Also see the options.resolution property.
          */
@@ -45876,14 +45898,21 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Class used to host texture specific utilities
+     * Class used to host RGBD texture specific utilities
      */
-    export class BRDFTextureTools {
+    export class RGBDTextureTools {
         /**
-         * Expand the BRDF Texture from RGBD to Half Float if necessary.
+         * Expand the RGBD Texture from RGBD to Half Float if possible.
          * @param texture the texture to expand.
          */
-        private static _ExpandDefaultBRDFTexture;
+        static ExpandRGBDTexture(texture: Texture): void;
+    }
+}
+declare module BABYLON {
+    /**
+     * Class used to host texture specific utilities
+     */
+    export class BRDFTextureTools {
         /**
          * Gets a default environment BRDF for MS-BRDF Height Correlated BRDF
          * @param scene defines the hosting scene
@@ -46856,6 +46885,7 @@ declare module BABYLON {
         LIGHTMAPDIRECTUV: number;
         USELIGHTMAPASSHADOWMAP: boolean;
         GAMMALIGHTMAP: boolean;
+        RGBDLIGHTMAP: boolean;
         REFLECTION: boolean;
         REFLECTIONMAP_3D: boolean;
         REFLECTIONMAP_SPHERICAL: boolean;
@@ -52082,9 +52112,9 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Enum used to define well known values e.g. values automatically provided by the system
+     * Enum used to define system values e.g. values automatically provided by the system
      */
-    export enum NodeMaterialWellKnownValues {
+    export enum NodeMaterialSystemValues {
         /** World */
         World = 1,
         /** View */
@@ -52227,6 +52257,8 @@ declare module BABYLON {
         SAMPLER3DGREENDEPTH: boolean;
         SAMPLER3DBGRMAP: boolean;
         IMAGEPROCESSINGPOSTPROCESS: boolean;
+        /** MISC. */
+        BUMPDIRECTUV: number;
         constructor();
         setValue(name: string, value: boolean): void;
     }
@@ -52512,7 +52544,7 @@ declare module BABYLON {
         /**
          * Gets or sets the texture associated with the node
          */
-        texture: Nullable<BaseTexture>;
+        texture: Nullable<Texture>;
         /**
          * Create a new TextureBlock
          * @param name defines the block name
@@ -52690,6 +52722,12 @@ declare module BABYLON {
             [key: string]: string;
         };
         /**
+         * Gets the list of emitted extensions
+         */
+        extensions: {
+            [key: string]: string;
+        };
+        /**
          * Gets the target of the compilation state
          */
         target: NodeMaterialBlockTargets;
@@ -52736,6 +52774,8 @@ declare module BABYLON {
         /** @hidden */
         _getGLType(type: NodeMaterialBlockConnectionPointTypes): string;
         /** @hidden */
+        _emitExtension(name: string, extension: string): void;
+        /** @hidden */
         _emitFunction(name: string, code: string, comments: string): void;
         /** @hidden */
         _emitCodeFromInclude(includeName: string, comments: string, options?: {
@@ -53018,8 +53058,14 @@ declare module BABYLON {
         private _valueCallback;
         private _type;
         private _animationType;
-        /** @hidden */
-        _wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        /** Gets or set a value used to limit the range of float values */
+        min: number;
+        /** Gets or set a value used to limit the range of float values */
+        max: number;
+        /** Gets or sets a value used by the Node Material editor to determine how to configure the current value if it is a matrix */
+        matrixMode: number;
+        /** @hidden */
+        _systemValue: Nullable<NodeMaterialSystemValues>;
         /** Gets or sets a boolean indicating that this input can be edited in the Inspector (false by default) */
         visibleInInspector: boolean;
         /**
@@ -53044,11 +53090,11 @@ declare module BABYLON {
          */
         setAsAttribute(attributeName?: string): InputBlock;
         /**
-         * Set the source of this connection point to a well known value
-         * @param value define the well known value to use (world, view, etc...) or null to switch to manual value
+         * Set the source of this connection point to a system value
+         * @param value define the system value to use (world, view, etc...) or null to switch to manual value
          * @returns the current connection point
          */
-        setAsWellKnownValue(value: Nullable<NodeMaterialWellKnownValues>): InputBlock;
+        setAsSystemValue(value: Nullable<NodeMaterialSystemValues>): InputBlock;
         /**
          * Gets or sets the value of that point.
          * Please note that this value will be ignored if valueCallback is defined
@@ -53087,13 +53133,13 @@ declare module BABYLON {
          */
         isVarying: boolean;
         /**
-         * Gets a boolean indicating that the current connection point is a well known value
+         * Gets a boolean indicating that the current connection point is a system value
          */
-        readonly isWellKnownValue: boolean;
+        readonly isSystemValue: boolean;
         /**
-         * Gets or sets the current well known value or null if not defined as well know value
+         * Gets or sets the current well known value or null if not defined as a system value
          */
-        wellKnownValue: Nullable<NodeMaterialWellKnownValues>;
+        systemValue: Nullable<NodeMaterialSystemValues>;
         /**
          * Gets the current class name
          * @returns the class name
@@ -53105,6 +53151,7 @@ declare module BABYLON {
          */
         animate(scene: Scene): void;
         private _emitDefine;
+        initialize(state: NodeMaterialBuildState): void;
         /**
          * Set the input block to its default value (based on its type)
          */
@@ -53486,6 +53533,59 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to pertub normals based on a normal map
+     */
+    export class PerturbNormalBlock extends NodeMaterialBlock {
+        private _tangentSpaceParameterName;
+        /** Gets or sets a boolean indicating that normal should be inverted on X axis */
+        invertX: boolean;
+        /** Gets or sets a boolean indicating that normal should be inverted on Y axis */
+        invertY: boolean;
+        /**
+         * Create a new PerturbNormalBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the world position input component
+         */
+        readonly worldPosition: NodeMaterialConnectionPoint;
+        /**
+         * Gets the world normal input component
+         */
+        readonly worldNormal: NodeMaterialConnectionPoint;
+        /**
+         * Gets the uv input component
+         */
+        readonly uv: NodeMaterialConnectionPoint;
+        /**
+        * Gets the normal map color input component
+        */
+        readonly normalMapColor: NodeMaterialConnectionPoint;
+        /**
+        * Gets the strength input component
+        */
+        readonly strength: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines): void;
+        bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh): void;
+        autoConfigure(material: NodeMaterial): void;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+        protected _dumpPropertiesCode(): string;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
+    }
+}
+declare module BABYLON {
+    /**
      * Block used to add support for scene fog
      */
     export class FogBlock extends NodeMaterialBlock {
@@ -53788,6 +53888,22 @@ declare module BABYLON {
          */
         readonly input: NodeMaterialConnectionPoint;
         /**
+         * Gets the source min input component
+         */
+        readonly sourceMin: NodeMaterialConnectionPoint;
+        /**
+         * Gets the source max input component
+         */
+        readonly sourceMax: NodeMaterialConnectionPoint;
+        /**
+         * Gets the target min input component
+         */
+        readonly targetMin: NodeMaterialConnectionPoint;
+        /**
+         * Gets the target max input component
+         */
+        readonly targetMax: NodeMaterialConnectionPoint;
+        /**
          * Gets the output component
          */
         readonly output: NodeMaterialConnectionPoint;
@@ -53872,6 +53988,8 @@ declare module BABYLON {
          */
         readonly output: NodeMaterialConnectionPoint;
         protected _buildBlock(state: NodeMaterialBuildState): this;
+        serialize(): any;
+        _deserialize(serializationObject: any, scene: Scene, rootUrl: string): void;
     }
 }
 declare module BABYLON {
@@ -54192,11 +54310,11 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
-     * Block used to get the opposite of a value
+     * Block used to get the opposite (1 - x) of a value
      */
-    export class OppositeBlock extends NodeMaterialBlock {
+    export class OneMinusBlock extends NodeMaterialBlock {
         /**
-         * Creates a new OppositeBlock
+         * Creates a new OneMinusBlock
          * @param name defines the block name
          */
         constructor(name: string);
@@ -54348,6 +54466,88 @@ declare module BABYLON {
 }
 declare module BABYLON {
     /**
+     * Block used to get the distance between 2 values
+     */
+    export class DistanceBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new DistanceBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the left operand input component
+         */
+        readonly left: NodeMaterialConnectionPoint;
+        /**
+         * Gets the right operand input component
+         */
+        readonly right: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get the length of a vector
+     */
+    export class LengthBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new LengthBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the value input component
+         */
+        readonly value: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
+     * Block used to get negative version of a value (i.e. x * -1)
+     */
+    export class NegateBlock extends NodeMaterialBlock {
+        /**
+         * Creates a new NegateBlock
+         * @param name defines the block name
+         */
+        constructor(name: string);
+        /**
+         * Gets the current class name
+         * @returns the class name
+         */
+        getClassName(): string;
+        /**
+         * Gets the value input component
+         */
+        readonly value: NodeMaterialConnectionPoint;
+        /**
+         * Gets the output component
+         */
+        readonly output: NodeMaterialConnectionPoint;
+        protected _buildBlock(state: NodeMaterialBuildState): this;
+    }
+}
+declare module BABYLON {
+    /**
      * Effect Render Options
      */
     export interface IEffectRendererOptions {
@@ -54384,6 +54584,11 @@ declare module BABYLON {
          */
         setViewport(viewport?: Viewport): void;
         /**
+         * Binds the embedded attributes buffer to the effect.
+         * @param effect Defines the effect to bind the attributes for
+         */
+        bindBuffers(effect: Effect): void;
+        /**
          * Sets the current effect wrapper to use during draw.
          * The effect needs to be ready before calling this api.
          * This also sets the default full screen position attribute.
@@ -56135,6 +56340,18 @@ declare module BABYLON {
          */
         createCrowd(maxAgents: number, maxAgentRadius: number, scene: Scene): ICrowd;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -56186,6 +56403,18 @@ declare module BABYLON {
          */
         agentGoto(index: number, destination: Vector3): void;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -56358,6 +56587,18 @@ declare module BABYLON {
          */
         createCrowd(maxAgents: number, maxAgentRadius: number, scene: Scene): ICrowd;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Disposes
          */
         dispose(): void;
@@ -56447,6 +56688,18 @@ declare module BABYLON {
          */
         update(deltaTime: number): void;
         /**
+         * Set the Bounding box extent for doing spatial queries (getClosestPoint, getRandomPointAround, ...)
+         * The queries will try to find a solution within those bounds
+         * default is (1,1,1)
+         * @param extent x,y,z value that define the extent around the queries point of reference
+         */
+        setDefaultQueryExtent(extent: Vector3): void;
+        /**
+         * Get the Bounding box extent specified by setDefaultQueryExtent
+         * @returns the box extent values
+         */
+        getDefaultQueryExtent(): Vector3;
+        /**
          * Release all resources
          */
         dispose(): void;
@@ -64058,6 +64311,10 @@ declare module BABYLON.GUI {
          */
         onImageLoadedObservable: BABYLON.Observable<Image>;
         /**
+         * BABYLON.Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
+         */
+        onSVGAttributesComputedObservable: BABYLON.Observable<Image>;
+        /**
          * Gets a boolean indicating that the content is loaded
          */
         readonly isLoaded: boolean;
@@ -64120,6 +64377,15 @@ declare module BABYLON.GUI {
          */
         source: BABYLON.Nullable<string>;
         /**
+         * Checks for svg document with icon id present
+         */
+        private _svgCheck;
+        /**
+         * Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
+         * given external svg file and icon id
+         */
+        private _getSVGAttribs;
+        /**
          * Gets or sets the cell width to use when animation sheet is enabled
          * @see http://doc.babylonjs.com/how_to/gui#image
          */

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

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

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

@@ -1440,6 +1440,10 @@ declare module BABYLON.GUI {
          */
         onImageLoadedObservable: BABYLON.Observable<Image>;
         /**
+         * BABYLON.Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
+         */
+        onSVGAttributesComputedObservable: BABYLON.Observable<Image>;
+        /**
          * Gets a boolean indicating that the content is loaded
          */
         readonly isLoaded: boolean;
@@ -1502,6 +1506,15 @@ declare module BABYLON.GUI {
          */
         source: BABYLON.Nullable<string>;
         /**
+         * Checks for svg document with icon id present
+         */
+        private _svgCheck;
+        /**
+         * Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
+         * given external svg file and icon id
+         */
+        private _getSVGAttribs;
+        /**
          * Gets or sets the cell width to use when animation sheet is enabled
          * @see http://doc.babylonjs.com/how_to/gui#image
          */

+ 125 - 41
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__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -366,7 +366,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");
 /* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -509,7 +509,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");
 /* 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");
@@ -1647,7 +1647,7 @@ var Button = /** @class */ (function (_super) {
 __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");
 /* 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");
@@ -1828,7 +1828,7 @@ var Checkbox = /** @class */ (function (_super) {
 __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");
 /* 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");
@@ -3215,7 +3215,7 @@ var ColorPicker = /** @class */ (function (_super) {
 __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");
 /* 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");
@@ -3628,7 +3628,7 @@ var Container = /** @class */ (function (_super) {
 "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");
 /* 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");
@@ -5819,7 +5819,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");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__);
 
 
@@ -6275,7 +6275,7 @@ var Grid = /** @class */ (function (_super) {
 __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");
 /* 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");
 
@@ -6311,6 +6311,10 @@ var Image = /** @class */ (function (_super) {
          * Observable notified when the content is loaded
          */
         _this.onImageLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["Observable"]();
+        /**
+         * Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
+         */
+        _this.onSVGAttributesComputedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["Observable"]();
         _this.source = url;
         return _this;
     }
@@ -6619,6 +6623,9 @@ var Image = /** @class */ (function (_super) {
             }
             this._loaded = false;
             this._source = value;
+            if (value) {
+                this._svgCheck(value);
+            }
             this._domImage = document.createElement("img");
             this._domImage.onload = function () {
                 _this._onImageLoaded();
@@ -6631,6 +6638,82 @@ var Image = /** @class */ (function (_super) {
         enumerable: true,
         configurable: true
     });
+    /**
+     * Checks for svg document with icon id present
+     */
+    Image.prototype._svgCheck = function (value) {
+        var _this = this;
+        if ((value.search(/.svg#/gi) !== -1) && (value.indexOf("#") === value.lastIndexOf("#"))) {
+            var svgsrc = value.split('#')[0];
+            var elemid = value.split('#')[1];
+            // check if object alr exist in document
+            var svgExist = document.body.querySelector('object[data="' + svgsrc + '"]');
+            if (svgExist) {
+                if (svgExist.contentDocument) {
+                    // svg object alr exists
+                    this._getSVGAttribs(svgExist, elemid);
+                }
+                else {
+                    // wait for object to load
+                    svgExist.addEventListener("load", function () {
+                        _this._getSVGAttribs(svgExist, elemid);
+                    });
+                }
+            }
+            else {
+                // create document object
+                var svgImage = document.createElement("object");
+                svgImage.data = svgsrc;
+                svgImage.type = "image/svg+xml";
+                svgImage.width = "0%";
+                svgImage.height = "0%";
+                document.body.appendChild(svgImage);
+                // when the object has loaded, get the element attribs
+                svgImage.onload = function () {
+                    var svgobj = document.body.querySelector('object[data="' + svgsrc + '"]');
+                    if (svgobj) {
+                        _this._getSVGAttribs(svgobj, elemid);
+                    }
+                };
+            }
+        }
+    };
+    /**
+     * Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
+     * given external svg file and icon id
+     */
+    Image.prototype._getSVGAttribs = function (svgsrc, elemid) {
+        var svgDoc = svgsrc.contentDocument;
+        // get viewbox width and height, get svg document width and height in px
+        if (svgDoc && svgDoc.documentElement) {
+            var vb = svgDoc.documentElement.getAttribute("viewBox");
+            var docwidth = Number(svgDoc.documentElement.getAttribute("width"));
+            var docheight = Number(svgDoc.documentElement.getAttribute("height"));
+            // get element bbox and matrix transform
+            var elem = svgDoc.getElementById(elemid);
+            if (elem instanceof SVGElement && vb && docwidth && docheight) {
+                var vb_width = Number(vb.split(" ")[2]);
+                var vb_height = Number(vb.split(" ")[3]);
+                var elem_bbox = elem.getBBox();
+                var elem_matrix_a = 1;
+                var elem_matrix_d = 1;
+                var elem_matrix_e = 0;
+                var elem_matrix_f = 0;
+                if (elem.transform && elem.transform.baseVal.consolidate()) {
+                    elem_matrix_a = elem.transform.baseVal.consolidate().matrix.a;
+                    elem_matrix_d = elem.transform.baseVal.consolidate().matrix.d;
+                    elem_matrix_e = elem.transform.baseVal.consolidate().matrix.e;
+                    elem_matrix_f = elem.transform.baseVal.consolidate().matrix.f;
+                }
+                // compute source coordinates and dimensions
+                this.sourceLeft = ((elem_matrix_a * elem_bbox.x + elem_matrix_e) * docwidth) / vb_width;
+                this.sourceTop = ((elem_matrix_d * elem_bbox.y + elem_matrix_f) * docheight) / vb_height;
+                this.sourceWidth = (elem_bbox.width * elem_matrix_a) * (docwidth / vb_width);
+                this.sourceHeight = (elem_bbox.height * elem_matrix_d) * (docheight / vb_height);
+                this.onSVGAttributesComputedObservable.notifyObservers(this);
+            }
+        }
+    };
     Object.defineProperty(Image.prototype, "cellWidth", {
         /**
          * Gets or sets the cell width to use when animation sheet is enabled
@@ -6858,6 +6941,7 @@ var Image = /** @class */ (function (_super) {
     Image.prototype.dispose = function () {
         _super.prototype.dispose.call(this);
         this.onImageLoadedObservable.clear();
+        this.onSVGAttributesComputedObservable.clear();
     };
     Image._WorkingCanvas = null;
     // Static
@@ -7050,7 +7134,7 @@ var InputPassword = /** @class */ (function (_super) {
 __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");
 /* 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");
@@ -8061,7 +8145,7 @@ var InputText = /** @class */ (function (_super) {
 __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__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__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");
@@ -8329,7 +8413,7 @@ var Line = /** @class */ (function (_super) {
 __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");
 /* 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");
@@ -8596,7 +8680,7 @@ var MultiLine = /** @class */ (function (_super) {
 __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");
 /* 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");
@@ -8941,7 +9025,7 @@ var Rectangle = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScrollViewer", function() { return ScrollViewer; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Events/pointerEvents */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Events/pointerEvents */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Events_pointerEvents__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _rectangle__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../rectangle */ "./2D/controls/rectangle.ts");
 /* harmony import */ var _grid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../grid */ "./2D/controls/grid.ts");
@@ -10032,7 +10116,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");
 /* 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");
@@ -10933,7 +11017,7 @@ var Slider = /** @class */ (function (_super) {
 __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");
 /* 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");
@@ -11199,7 +11283,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");
 /* 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");
@@ -11660,7 +11744,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");
 /* 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");
@@ -12041,7 +12125,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__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -12265,7 +12349,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__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 
 
@@ -12398,7 +12482,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__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -12541,7 +12625,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");
 /* 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");
 
@@ -12848,7 +12932,7 @@ var ValueAndUnit = /** @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");
 /* 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");
 
@@ -12891,7 +12975,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__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__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");
@@ -13068,7 +13152,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");
 /* 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");
 
@@ -13225,7 +13309,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");
 /* 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");
 
@@ -13631,7 +13715,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");
 /* 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");
@@ -13717,7 +13801,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_Maths_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__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");
@@ -14193,7 +14277,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__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__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");
@@ -14248,7 +14332,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");
 /* 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");
@@ -14375,7 +14459,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");
 /* 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");
@@ -14460,7 +14544,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");
 /* 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");
 
@@ -14585,7 +14669,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");
 /* 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");
 
@@ -14776,7 +14860,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");
 /* 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");
 
@@ -14867,7 +14951,7 @@ var GUI3DManager = /** @class */ (function () {
         this.onPickedPointChangedObservable.notifyObservers(null);
     };
     GUI3DManager.prototype._doPicking = function (pi) {
-        if (!this._utilityLayer || !this._utilityLayer.utilityLayerScene.activeCamera) {
+        if (!this._utilityLayer || !this._utilityLayer.shouldRender || !this._utilityLayer.utilityLayerScene.activeCamera) {
             return false;
         }
         var pointerEvent = (pi.event);
@@ -15043,7 +15127,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");
 /* 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");
@@ -15365,7 +15449,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");
 /* 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';
@@ -15387,7 +15471,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");
 /* 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';
@@ -15410,7 +15494,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__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Misc/perfCounter");
+/* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math */ "babylonjs/Maths/math");
 /* harmony import */ var babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -15704,14 +15788,14 @@ if (typeof globalObject !== "undefined") {
 
 /***/ }),
 
-/***/ "babylonjs/Misc/perfCounter":
+/***/ "babylonjs/Maths/math":
 /*!****************************************************************************************************!*\
   !*** 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__;
 
 /***/ })
 

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


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

@@ -1483,6 +1483,10 @@ declare module "babylonjs-gui/2D/controls/image" {
          */
         onImageLoadedObservable: Observable<Image>;
         /**
+         * Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
+         */
+        onSVGAttributesComputedObservable: Observable<Image>;
+        /**
          * Gets a boolean indicating that the content is loaded
          */
         readonly isLoaded: boolean;
@@ -1545,6 +1549,15 @@ declare module "babylonjs-gui/2D/controls/image" {
          */
         source: Nullable<string>;
         /**
+         * Checks for svg document with icon id present
+         */
+        private _svgCheck;
+        /**
+         * Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
+         * given external svg file and icon id
+         */
+        private _getSVGAttribs;
+        /**
          * Gets or sets the cell width to use when animation sheet is enabled
          * @see http://doc.babylonjs.com/how_to/gui#image
          */
@@ -5313,6 +5326,10 @@ declare module BABYLON.GUI {
          */
         onImageLoadedObservable: BABYLON.Observable<Image>;
         /**
+         * BABYLON.Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
+         */
+        onSVGAttributesComputedObservable: BABYLON.Observable<Image>;
+        /**
          * Gets a boolean indicating that the content is loaded
          */
         readonly isLoaded: boolean;
@@ -5375,6 +5392,15 @@ declare module BABYLON.GUI {
          */
         source: BABYLON.Nullable<string>;
         /**
+         * Checks for svg document with icon id present
+         */
+        private _svgCheck;
+        /**
+         * Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
+         * given external svg file and icon id
+         */
+        private _getSVGAttribs;
+        /**
          * Gets or sets the cell width to use when animation sheet is enabled
          * @see http://doc.babylonjs.com/how_to/gui#image
          */

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

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

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

@@ -27,7 +27,7 @@ If using TypeScript, the typing needs to be added to tsconfig.json:
     "types": [
         "babylonjs",
         "babylonjs-gui",
-        "angularFTW"
+        "otherImportsYouMightNeed"
     ],
     ....
 ```

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js


+ 16 - 4
dist/preview release/inspector/babylon.inspector.bundle.max.js

@@ -45088,6 +45088,8 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _lines_vector4LineComponent__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../../lines/vector4LineComponent */ "./components/actionTabs/lines/vector4LineComponent.tsx");
 /* harmony import */ var _lines_vector2LineComponent__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../../lines/vector2LineComponent */ "./components/actionTabs/lines/vector2LineComponent.tsx");
 /* harmony import */ var _lines_textureLinkLineComponent__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../../lines/textureLinkLineComponent */ "./components/actionTabs/lines/textureLinkLineComponent.tsx");
+/* harmony import */ var _lines_sliderLineComponent__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../../lines/sliderLineComponent */ "./components/actionTabs/lines/sliderLineComponent.tsx");
+
 
 
 
@@ -45127,7 +45129,7 @@ var NodeMaterialPropertyGridComponent = /** @class */ (function (_super) {
     NodeMaterialPropertyGridComponent.prototype.renderInputValues = function () {
         var _this = this;
         var configurableInputBlocks = this.props.material.getInputBlocks().filter(function (block) {
-            return block.visibleInInspector && block.isUniform && !block.isWellKnownValue;
+            return block.visibleInInspector && block.isUniform && !block.isSystemValue;
         }).sort(function (a, b) {
             return a.name.localeCompare(b.name);
         });
@@ -45137,6 +45139,12 @@ var NodeMaterialPropertyGridComponent = /** @class */ (function (_super) {
         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__["LineContainerComponent"], { globalState: this.props.globalState, title: "INPUTS" }, configurableInputBlocks.map(function (block) {
             switch (block.type) {
                 case babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_2__["NodeMaterialBlockConnectionPointTypes"].Float:
+                    var cantDisplaySlider = (isNaN(block.min) || isNaN(block.max) || block.min === block.max);
+                    return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](react__WEBPACK_IMPORTED_MODULE_1__["Fragment"], null,
+                        cantDisplaySlider &&
+                            react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_floatLineComponent__WEBPACK_IMPORTED_MODULE_7__["FloatLineComponent"], { key: block.name, lockObject: _this.props.lockObject, label: block.name, target: block, propertyName: "value", onPropertyChangedObservable: _this.props.onPropertyChangedObservable }),
+                        !cantDisplaySlider &&
+                            react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_sliderLineComponent__WEBPACK_IMPORTED_MODULE_13__["SliderLineComponent"], { key: block.name, label: block.name, target: block, propertyName: "value", step: 0.1, minimum: block.min, maximum: block.max, onPropertyChangedObservable: _this.props.onPropertyChangedObservable })));
                     return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_floatLineComponent__WEBPACK_IMPORTED_MODULE_7__["FloatLineComponent"], { key: block.name, lockObject: _this.props.lockObject, label: block.name, target: block, propertyName: "value", onPropertyChangedObservable: _this.props.onPropertyChangedObservable }));
                 case babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_2__["NodeMaterialBlockConnectionPointTypes"].Color3:
                 case babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_2__["NodeMaterialBlockConnectionPointTypes"].Color4:
@@ -45972,7 +45980,9 @@ var MeshPropertyGridComponent = /** @class */ (function (_super) {
             if (!mesh.reservedDataStore) {
                 mesh.reservedDataStore = {};
             }
-            mesh.reservedDataStore.originalMaterial = mesh.material;
+            if (!mesh.reservedDataStore.originalMaterial) {
+                mesh.reservedDataStore.originalMaterial = mesh.material;
+            }
             var normalMaterial = new BABYLON.NormalMaterial("normalMaterial", scene);
             normalMaterial.disableLighting = true;
             if (mesh.material) {
@@ -45996,7 +46006,9 @@ var MeshPropertyGridComponent = /** @class */ (function (_super) {
             if (!mesh.reservedDataStore) {
                 mesh.reservedDataStore = {};
             }
-            mesh.reservedDataStore.originalMaterial = mesh.material;
+            if (!mesh.reservedDataStore.originalMaterial) {
+                mesh.reservedDataStore.originalMaterial = mesh.material;
+            }
             var vertexColorMaterial = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_2__["StandardMaterial"]("vertex colors", scene);
             vertexColorMaterial.disableLighting = true;
             vertexColorMaterial.emissiveColor = babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_2__["Color3"].White();
@@ -46056,7 +46068,7 @@ var MeshPropertyGridComponent = /** @class */ (function (_super) {
         var mesh = this.props.mesh;
         var scene = mesh.getScene();
         var displayNormals = mesh.material != null && mesh.material.getClassName() === "NormalMaterial";
-        var displayVertexColors = mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial;
+        var displayVertexColors = !!(mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial);
         var renderNormalVectors = (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) ? true : false;
         var renderWireframeOver = (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) ? true : false;
         var morphTargets = [];

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


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

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "4.1.0-alpha.15",
+    "version": "4.1.0-alpha.19",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -29,12 +29,12 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-alpha.15",
-        "babylonjs-gui": "4.1.0-alpha.15",
-        "babylonjs-loaders": "4.1.0-alpha.15",
-        "babylonjs-materials": "4.1.0-alpha.15",
-        "babylonjs-serializers": "4.1.0-alpha.15",
-        "babylonjs-gltf2interface": "4.1.0-alpha.15"
+        "babylonjs": "4.1.0-alpha.19",
+        "babylonjs-gui": "4.1.0-alpha.19",
+        "babylonjs-loaders": "4.1.0-alpha.19",
+        "babylonjs-materials": "4.1.0-alpha.19",
+        "babylonjs-serializers": "4.1.0-alpha.19",
+        "babylonjs-gltf2interface": "4.1.0-alpha.19"
     },
     "devDependencies": {
         "@types/react": "~16.7.3",

+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.js

@@ -886,7 +886,7 @@ var OBJFileLoader = /** @class */ (function () {
         var lines = data.split('\n');
         //Look at each line
         for (var i = 0; i < lines.length; i++) {
-            var line = lines[i].trim();
+            var line = lines[i].trim().replace(/\s\s/g, " ");
             var result;
             //Comment or newLine
             if (line.length === 0 || line.charAt(0) === '#') {

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 1 - 0
dist/preview release/loaders/babylon.stlFileLoader.js

@@ -161,6 +161,7 @@ __webpack_require__.r(__webpack_exports__);
 
 
 
+
 /**
  * STL file type loader.
  * This is a babylon scene loader plugin.

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.stlFileLoader.js.map


+ 2 - 1
dist/preview release/loaders/babylonjs.loaders.js

@@ -1115,7 +1115,7 @@ var OBJFileLoader = /** @class */ (function () {
         var lines = data.split('\n');
         //Look at each line
         for (var i = 0; i < lines.length; i++) {
-            var line = lines[i].trim();
+            var line = lines[i].trim().replace(/\s\s/g, " ");
             var result;
             //Comment or newLine
             if (line.length === 0 || line.charAt(0) === '#') {
@@ -1484,6 +1484,7 @@ __webpack_require__.r(__webpack_exports__);
 
 
 
+
 /**
  * STL file type loader.
  * This is a babylon scene loader plugin.

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


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

@@ -2224,6 +2224,7 @@ declare module "babylonjs-loaders/STL/stlFileLoader" {
     import { ISceneLoaderPlugin, ISceneLoaderPluginExtensions } from "babylonjs/Loading/sceneLoader";
     import { AssetContainer } from "babylonjs/assetContainer";
     import { Scene } from "babylonjs/scene";
+    import "babylonjs/Helpers/sceneHelpers";
     /**
      * STL file type loader.
      * This is a babylon scene loader plugin.

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

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

Разница между файлами не показана из-за своего большого размера
+ 11 - 4
dist/preview release/materialsLibrary/babylon.gridMaterial.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gridMaterial.min.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Разница между файлами не показана из-за своего большого размера
+ 12 - 5
dist/preview release/materialsLibrary/babylonjs.materials.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/materialsLibrary/babylonjs.materials.min.js


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

@@ -459,7 +459,9 @@ declare module "babylonjs-materials/grid/grid.fragment" {
     };
 }
 declare module "babylonjs-materials/grid/grid.vertex" {
+    import "babylonjs/Shaders/ShadersInclude/instancesDeclaration";
     import "babylonjs/Shaders/ShadersInclude/fogVertexDeclaration";
+    import "babylonjs/Shaders/ShadersInclude/instancesVertex";
     import "babylonjs/Shaders/ShadersInclude/fogVertex";
     /** @hidden */
     export var gridVertexShader: {

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

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

Разница между файлами не показана из-за своего большого размера
+ 183 - 25
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts


Разница между файлами не показана из-за своего большого размера
+ 7 - 7
dist/preview release/nodeEditor/babylon.nodeEditor.js


Разница между файлами не показана из-за своего большого размера
+ 980 - 163
dist/preview release/nodeEditor/babylon.nodeEditor.max.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map


Разница между файлами не показана из-за своего большого размера
+ 396 - 52
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts


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

@@ -4,14 +4,14 @@
     },
     "name": "babylonjs-node-editor",
     "description": "The Babylon.js node material editor.",
-    "version": "4.1.0-alpha.15",
+    "version": "4.1.0-alpha.19",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
     },
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.1.0-alpha.15"
+        "babylonjs": "4.1.0-alpha.19"
     },
     "files": [
         "babylon.nodeEditor.max.js.map",

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

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

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

@@ -1 +1 @@
-{"engineOnly":167798,"sceneOnly":508287,"minGridMaterial":637946,"minStandardMaterial":767330}
+{"engineOnly":167802,"sceneOnly":508463,"minGridMaterial":638613,"minStandardMaterial":767889}

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

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

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

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

Разница между файлами не показана из-за своего большого размера
+ 8 - 8
dist/preview release/recast.js


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

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

Разница между файлами не показана из-за своего большого размера
+ 616 - 67
dist/preview release/viewer/babylon.module.d.ts


Разница между файлами не показана из-за своего большого размера
+ 111 - 91
dist/preview release/viewer/babylon.viewer.js


Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


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

@@ -2224,6 +2224,7 @@ declare module "babylonjs-loaders/STL/stlFileLoader" {
     import { ISceneLoaderPlugin, ISceneLoaderPluginExtensions } from "babylonjs/Loading/sceneLoader";
     import { AssetContainer } from "babylonjs/assetContainer";
     import { Scene } from "babylonjs/scene";
+    import "babylonjs/Helpers/sceneHelpers";
     /**
      * STL file type loader.
      * This is a babylon scene loader plugin.

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

@@ -29,6 +29,7 @@
 - Added support for sound sprites [Doc](https://doc.babylonjs.com/how_to/playing_sounds_and_music#playing-a-sound-sprite) ([Deltakosh](https://github.com/deltakosh/))
 - Display Oculus Quest controller when using a Quest in WebVR ([TrevorDev](https://github.com/TrevorDev))
 - Added startAndReleaseDragOnPointerEvents property to pointerDragBehavior which can be set to false for custom drag triggering ([TrevorDev](https://github.com/TrevorDev))
+- Added optional picking predicate to pointerDragBehavior for filtering affected meshes ([Exolun](https://github.com/Exolun))
 - Effect renderer to render one or multiple shader effects to a texture ([TrevorDev](https://github.com/TrevorDev))
 - Added url parameters to web request modifiers ([PierreLeBlond](https://github.com/PierreLeBlond))
 - Added `VRExperienceHelper.exitVROnDoubleTap` ([Deltakosh](https://github.com/deltakosh/))
@@ -62,6 +63,7 @@
 - Added `ShadowGenerator.onAfterShadowMapRenderObservable` and `ShadowGenerator.onAfterShadowMapMeshRenderObservable` ([Deltakosh](https://github.com/deltakosh/))
 - Added support for side by side and top bottom images in the `PhotoDome` ([Deltakosh](https://github.com/deltakosh/))
 - Added playground ts-local (TypeScript support for local playground) ([pjoe](https://github.com/pjoe/))
+- Added RGBD Texture tools [Sebavan](https://github.com/sebavan/)
 
 ### Meshes
 - Added `TransformNode.instantiateHierarchy()` which try to instantiate (or clone) a node and its entire hiearchy ([Deltakosh](https://github.com/deltakosh/))
@@ -102,6 +104,8 @@
 - Added `Button.delegatePickingToChildren` to let buttons delegate hit testing to embedded controls ([Deltakosh](https://github.com/deltakosh/))
 - Added `Container.maxLayoutCycle` and `Container.logLayoutCycleErrors` to get more control over layout cycles ([Deltakosh](https://github.com/deltakosh/))
 - Added `StackPanel.ignoreLayoutWarnings` to disable console warnings when controls with percentage size are added to a StackPanel ([Deltakosh](https://github.com/deltakosh/))
+- Added `_getSVGAttribs` functionality for loading multiple svg icons from an external svg file via icon id.([lockphase](https://github.com/lockphase/))
+
 
 ### Navigation Mesh
 - Added moveAlong function to cast a segment on mavmesh ([CedricGuillemet](https://github.com/CedricGuillemet/))
@@ -116,7 +120,7 @@
 - Removing assetContainer from scene will also remove gui layers ([TrevorDev](https://github.com/TrevorDev))
 - A scene's input manager not adding key listeners when the canvas is already focused ([Poolminer](https://github.com/Poolminer))
 - Runtime animation `goToFrame` when going back in time now correctly triggers future events when reached ([zakhenry](https://github.com/zakhenry))
-- Fixed bug in Ray.intersectsTriangle where the barycentric coordinates `bu` and `bv` being returned is actually `bv` and `bw`. ([bghgary](https://github.com/bghgary))
+- Fixed bug in `Ray.intersectsTriangle` where the barycentric coordinates `bu` and `bv` being returned is actually `bv` and `bw`. ([bghgary](https://github.com/bghgary))
 - Do not call onError when creating a texture when falling back to another loader ([TrevorDev](https://github.com/TrevorDev))
 - Context loss should not cause PBR materials to render black or instances to stop rendering ([TrevorDev](https://github.com/TrevorDev))
 - Only cast pointer ray input when pointer is locked in webVR ([TrevorDev](https://github.com/TrevorDev))

+ 88 - 0
gui/src/2D/controls/image.ts

@@ -42,6 +42,11 @@ export class Image extends Control {
     public onImageLoadedObservable = new Observable<Image>();
 
     /**
+     * Observable notified when _sourceLeft, _sourceTop, _sourceWidth and _sourceHeight are computed
+     */
+    public onSVGAttributesComputedObservable = new Observable<Image>();
+
+    /**
      * Gets a boolean indicating that the content is loaded
      */
     public get isLoaded(): boolean {
@@ -353,6 +358,10 @@ export class Image extends Control {
         this._loaded = false;
         this._source = value;
 
+        if (value) {
+            this._svgCheck(value);
+        }
+
         this._domImage = document.createElement("img");
 
         this._domImage.onload = () => {
@@ -365,6 +374,84 @@ export class Image extends Control {
     }
 
     /**
+     * Checks for svg document with icon id present
+     */
+    private _svgCheck(value: string) {
+        if ((value.search(/.svg#/gi) !== -1) && (value.indexOf("#") === value.lastIndexOf("#"))) {
+            var svgsrc = value.split('#')[0];
+            var elemid = value.split('#')[1];
+            // check if object alr exist in document
+            var svgExist = <HTMLObjectElement> document.body.querySelector('object[data="' + svgsrc + '"]');
+            if (svgExist) {
+                if (svgExist.contentDocument) {
+                    // svg object alr exists
+                    this._getSVGAttribs(svgExist, elemid);
+                } else {
+                    // wait for object to load
+                    svgExist.addEventListener("load", () => {
+                        this._getSVGAttribs(svgExist, elemid);
+                    });
+                }
+
+            } else {
+                // create document object
+                var svgImage = document.createElement("object");
+                svgImage.data = svgsrc;
+                svgImage.type = "image/svg+xml";
+                svgImage.width = "0%";
+                svgImage.height = "0%";
+                document.body.appendChild(svgImage);
+                // when the object has loaded, get the element attribs
+                svgImage.onload = () => {
+                    var svgobj = <HTMLObjectElement> document.body.querySelector('object[data="' + svgsrc + '"]');
+                    if (svgobj) {
+                        this._getSVGAttribs(svgobj, elemid);
+                    }
+                };
+
+            }
+        }
+    }
+
+    /**
+     * Sets sourceLeft, sourceTop, sourceWidth, sourceHeight automatically
+	 * given external svg file and icon id
+     */
+    private _getSVGAttribs(svgsrc: HTMLObjectElement, elemid: string) {
+        var svgDoc = svgsrc.contentDocument;
+        // get viewbox width and height, get svg document width and height in px
+        if (svgDoc && svgDoc.documentElement) {
+            var vb = svgDoc.documentElement.getAttribute("viewBox");
+            var docwidth = Number(svgDoc.documentElement.getAttribute("width"));
+            var docheight = Number(svgDoc.documentElement.getAttribute("height"));
+            // get element bbox and matrix transform
+            var elem = <SVGGraphicsElement> <unknown> svgDoc.getElementById(elemid);
+            if (elem instanceof SVGElement && vb && docwidth && docheight) {
+                var vb_width = Number(vb.split(" ")[2]);
+                var vb_height = Number(vb.split(" ")[3]);
+                var elem_bbox = elem.getBBox();
+                var elem_matrix_a = 1;
+                var elem_matrix_d = 1;
+                var elem_matrix_e = 0;
+                var elem_matrix_f = 0;
+                if (elem.transform && elem.transform.baseVal.consolidate()) {
+                    elem_matrix_a = elem.transform.baseVal.consolidate().matrix.a;
+                    elem_matrix_d = elem.transform.baseVal.consolidate().matrix.d;
+                    elem_matrix_e = elem.transform.baseVal.consolidate().matrix.e;
+                    elem_matrix_f = elem.transform.baseVal.consolidate().matrix.f;
+                }
+
+                // compute source coordinates and dimensions
+                this.sourceLeft = ((elem_matrix_a * elem_bbox.x + elem_matrix_e) * docwidth) / vb_width;
+                this.sourceTop = ((elem_matrix_d * elem_bbox.y + elem_matrix_f) * docheight) / vb_height;
+                this.sourceWidth = (elem_bbox.width * elem_matrix_a) * (docwidth / vb_width);
+                this.sourceHeight = (elem_bbox.height * elem_matrix_d) * (docheight / vb_height);
+                this.onSVGAttributesComputedObservable.notifyObservers(this);
+            }
+        }
+    }
+
+    /**
      * Gets or sets the cell width to use when animation sheet is enabled
      * @see http://doc.babylonjs.com/how_to/gui#image
      */
@@ -648,6 +735,7 @@ export class Image extends Control {
     public dispose() {
         super.dispose();
         this.onImageLoadedObservable.clear();
+        this.onSVGAttributesComputedObservable.clear();
     }
 
     // Static

+ 1 - 1
gui/src/3D/gui3DManager.ts

@@ -106,7 +106,7 @@ export class GUI3DManager implements IDisposable {
     }
 
     private _doPicking(pi: PointerInfo): boolean {
-        if (!this._utilityLayer || !this._utilityLayer.utilityLayerScene.activeCamera) {
+        if (!this._utilityLayer || !this._utilityLayer.shouldRender || !this._utilityLayer.utilityLayerScene.activeCamera) {
             return false;
         }
 

+ 17 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/materials/nodeMaterialPropertyGridComponent.tsx

@@ -18,6 +18,7 @@ import { Vector2LineComponent } from '../../../lines/vector2LineComponent';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
 import { TextureLinkLineComponent } from '../../../lines/textureLinkLineComponent';
+import { SliderLineComponent } from '../../../lines/sliderLineComponent';
 
 interface INodeMaterialPropertyGridComponentProps {
     globalState: GlobalState;
@@ -64,7 +65,7 @@ export class NodeMaterialPropertyGridComponent extends React.Component<INodeMate
 
     renderInputValues() {
         let configurableInputBlocks = this.props.material.getInputBlocks().filter(block => {
-            return block.visibleInInspector && block.isUniform && !block.isWellKnownValue
+            return block.visibleInInspector && block.isUniform && !block.isSystemValue
         }).sort( (a, b) => {
             return a.name.localeCompare(b.name);
         });
@@ -79,6 +80,21 @@ export class NodeMaterialPropertyGridComponent extends React.Component<INodeMate
                     configurableInputBlocks.map(block => {
                         switch (block.type) {
                             case NodeMaterialBlockConnectionPointTypes.Float:
+                                    let cantDisplaySlider = (isNaN(block.min) || isNaN(block.max) || block.min === block.max);
+                                    return (
+                                        <>
+                                            {
+                                                cantDisplaySlider &&
+                                                <FloatLineComponent key={block.name} lockObject={this.props.lockObject} label={block.name} target={block} propertyName="value" 
+                                                    onPropertyChangedObservable={this.props.onPropertyChangedObservable}
+                                                />
+                                            }        
+                                            {
+                                                !cantDisplaySlider &&
+                                                <SliderLineComponent key={block.name} label={block.name} target={block} propertyName="value" step={0.1} minimum={block.min} maximum={block.max} onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
+                                            }
+                                        </>
+                                    );                                
                                 return (
                                     <FloatLineComponent key={block.name} lockObject={this.props.lockObject} label={block.name} target={block} propertyName="value" 
                                         onPropertyChangedObservable={this.props.onPropertyChangedObservable}

+ 7 - 3
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx

@@ -152,7 +152,9 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                 mesh.reservedDataStore = {};
             }
 
-            mesh.reservedDataStore.originalMaterial = mesh.material;
+            if (!mesh.reservedDataStore.originalMaterial) {
+                mesh.reservedDataStore.originalMaterial = mesh.material;
+            }
             const normalMaterial = new (BABYLON as any).NormalMaterial("normalMaterial", scene);
             normalMaterial.disableLighting = true;
             if (mesh.material) {
@@ -180,7 +182,9 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                 mesh.reservedDataStore = {};
             }
 
-            mesh.reservedDataStore.originalMaterial = mesh.material;
+            if (!mesh.reservedDataStore.originalMaterial) {
+                mesh.reservedDataStore.originalMaterial = mesh.material;
+            }
             const vertexColorMaterial = new StandardMaterial("vertex colors", scene);
             vertexColorMaterial.disableLighting = true;
             vertexColorMaterial.emissiveColor = Color3.White();
@@ -247,7 +251,7 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
         const scene = mesh.getScene();
 
         const displayNormals = mesh.material != null && mesh.material.getClassName() === "NormalMaterial";
-        const displayVertexColors = mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial;
+        const displayVertexColors = !!(mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial);
         const renderNormalVectors = (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) ? true : false;
         const renderWireframeOver = (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) ? true : false;
 

+ 1 - 1
loaders/src/OBJ/objFileLoader.ts

@@ -874,7 +874,7 @@ export class OBJFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPlugi
         var lines = data.split('\n');
         //Look at each line
         for (var i = 0; i < lines.length; i++) {
-            var line = lines[i].trim();
+            var line = lines[i].trim().replace(/\s\s/g, " ");
             var result;
 
             //Comment or newLine

+ 2 - 0
loaders/src/STL/stlFileLoader.ts

@@ -9,6 +9,8 @@ import { SceneLoader, ISceneLoaderPlugin, ISceneLoaderPluginExtensions } from "b
 import { AssetContainer } from "babylonjs/assetContainer";
 import { Scene } from "babylonjs/scene";
 
+import "babylonjs/Helpers/sceneHelpers";
+
 /**
  * STL file type loader.
  * This is a babylon scene loader plugin.

+ 12 - 12
localDev/lights.json

@@ -120,7 +120,7 @@
       "inputs": [],
       "type": 8,
       "mode": 1,
-      "wellKnownValue": null,
+      "systemValue": null,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -131,7 +131,7 @@
       "inputs": [],
       "type": 8,
       "mode": 1,
-      "wellKnownValue": null,
+      "systemValue": null,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -142,7 +142,7 @@
       "inputs": [],
       "type": 8,
       "mode": 1,
-      "wellKnownValue": null,
+      "systemValue": null,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -153,7 +153,7 @@
       "inputs": [],
       "type": 4,
       "mode": 1,
-      "wellKnownValue": null,
+      "systemValue": null,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -195,7 +195,7 @@
       "inputs": [],
       "type": 16,
       "mode": 1,
-      "wellKnownValue": null,
+      "systemValue": null,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -206,7 +206,7 @@
       "inputs": [],
       "type": 16,
       "mode": 1,
-      "wellKnownValue": null,
+      "systemValue": null,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -217,7 +217,7 @@
       "inputs": [],
       "type": 128,
       "mode": 0,
-      "wellKnownValue": 1,
+      "systemValue": 1,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -228,7 +228,7 @@
       "inputs": [],
       "type": 128,
       "mode": 0,
-      "wellKnownValue": 4,
+      "systemValue": 4,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -270,7 +270,7 @@
       "inputs": [],
       "type": 128,
       "mode": 0,
-      "wellKnownValue": 2,
+      "systemValue": 2,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -483,7 +483,7 @@
       "inputs": [],
       "type": 8,
       "mode": 1,
-      "wellKnownValue": null,
+      "systemValue": null,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -494,7 +494,7 @@
       "inputs": [],
       "type": 8,
       "mode": 0,
-      "wellKnownValue": 7,
+      "systemValue": 7,
       "animationType": 0,
       "visibleInInspector": false
     },
@@ -505,7 +505,7 @@
       "inputs": [],
       "type": 32,
       "mode": 0,
-      "wellKnownValue": 8,
+      "systemValue": 8,
       "animationType": 0,
       "visibleInInspector": false,
       "valueType": "BABYLON.Color3",

+ 5 - 4
materialsLibrary/src/grid/grid.vertex.fx

@@ -10,11 +10,11 @@ attribute vec2 uv;
 attribute vec2 uv2;
 #endif
 
+#include<instancesDeclaration>
+
 // Uniforms
 uniform mat4 projection;
-uniform mat4 world;
 uniform mat4 view;
-uniform mat4 worldView;
 
 // Varying
 varying vec3 vPosition;
@@ -29,14 +29,15 @@ uniform vec2 vOpacityInfos;
 #endif
 
 void main(void) {
+	#include<instancesVertex>
 
     #ifdef FOG
-    vec4 worldPos = world * vec4(position, 1.0);
+    vec4 worldPos = finalWorld * vec4(position, 1.0);
     #endif
 
     #include<fogVertex>
 
-    vec4 cameraSpacePosition = worldView * vec4(position, 1.0);
+    vec4 cameraSpacePosition = view * finalWorld * vec4(position, 1.0);
     gl_Position = projection * cameraSpacePosition;
 
 #ifdef OPACITY

+ 10 - 3
materialsLibrary/src/grid/gridMaterial.ts

@@ -23,6 +23,7 @@ class GridMaterialDefines extends MaterialDefines {
     public PREMULTIPLYALPHA = false;
     public UV1 = false;
     public UV2 = false;
+    public INSTANCES = false;
 
     constructor() {
         super();
@@ -160,6 +161,9 @@ export class GridMaterial extends PushMaterial {
 
         MaterialHelper.PrepareDefinesForMisc(mesh, scene, false, false, this.fogEnabled, false, defines);
 
+        // Values that need to be evaluated on every frame
+        MaterialHelper.PrepareDefinesForFrameBoundValues(scene, scene.getEngine(), defines, !!useInstances);
+
         // Get correct effect
         if (defines.isDirty) {
             defines.markAsProcessed();
@@ -176,11 +180,13 @@ export class GridMaterial extends PushMaterial {
                 attribs.push(VertexBuffer.UV2Kind);
             }
 
+            MaterialHelper.PrepareAttributesForInstances(attribs, defines);
+
             // Defines
             var join = defines.toString();
             subMesh.setEffect(scene.getEngine().createEffect("grid",
                 attribs,
-                ["projection", "worldView", "mainColor", "lineColor", "gridControl", "gridOffset", "vFogInfos", "vFogColor", "world", "view",
+                ["projection", "mainColor", "lineColor", "gridControl", "gridOffset", "vFogInfos", "vFogColor", "world", "view",
                     "opacityMatrix", "vOpacityInfos"],
                 ["opacitySampler"],
                 join,
@@ -214,8 +220,9 @@ export class GridMaterial extends PushMaterial {
         this._activeEffect = effect;
 
         // Matrices
-        this.bindOnlyWorldMatrix(world);
-        this._activeEffect.setMatrix("worldView", world.multiply(scene.getViewMatrix()));
+        if (!defines.INSTANCES) {
+            this.bindOnlyWorldMatrix(world);
+        }
         this._activeEffect.setMatrix("view", scene.getViewMatrix());
         this._activeEffect.setMatrix("projection", scene.getProjectionMatrix());
 

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

@@ -246,7 +246,7 @@ vec4 color = vec4(finalDiffuse + finalSpecular, alpha);
 // We first move from gamma to linear.
 #ifdef IMAGEPROCESSINGPOSTPROCESS
 	color.rgb = toLinearSpace(color.rgb);
-#elif IMAGEPROCESSING
+#elif defined(IMAGEPROCESSING)
     color.rgb = toLinearSpace(color.rgb);
     color = applyImageProcessing(color);
 #endif

+ 43 - 0
nodeEditor/public/index-local.html

@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+    <title>Node Material Editor - Local Development</title>    
+    <meta name="viewport" content="width=device-width, user-scalable=no">
+    <link rel="shortcut icon" href="https://www.babylonjs.com/favicon.ico">
+
+    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+    <script src="../../Tools/DevLoader/BabylonLoader.js"></script>
+    <link rel="stylesheet" href="https://use.typekit.net/cta4xsb.css"></style>
+
+    <style>
+        html,
+        body {
+            width: 100%;
+            height: 100%;
+            padding: 0;
+            margin: 0;
+            overflow: hidden;
+        }
+
+        #host-element {
+            width: 100%;
+            height: 100%;            
+        }
+    </style>
+</head>
+
+<body>
+    <div id="host-element">
+    </div>
+    <script>
+        // Load the scripts + map file to allow vscode debug.
+        BABYLONDEVTOOLS.Loader
+            .require("index.js")
+            .load(() => {
+                BABYLONDEVTOOLS.Loader.debugShortcut(engine);
+            });
+    </script>
+</body>
+
+</html>

+ 42 - 0
nodeEditor/public/index.html

@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+    <title>Babylon.js Node Material Editor</title>
+
+    <meta name="viewport" content="width=device-width, user-scalable=no">
+    <link rel="shortcut icon" href="https://www.babylonjs.com/favicon.ico">
+
+    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+    <link rel="stylesheet" href="https://use.typekit.net/cta4xsb.css"></style>
+    <script src="https://preview.babylonjs.com/babylon.js"></script>
+    <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
+    <script src="https://preview.babylonjs.com/nodeEditor/babylon.nodeEditor.js"></script>    
+    
+    <style>
+        html,
+        body {
+            width: 100%;
+            height: 100%;
+            padding: 0;
+            margin: 0;
+            overflow: hidden;
+        }
+
+        #host-element {
+            width: 100%;
+            height: 100%;               
+            padding: 0;
+            margin: 0;
+            overflow: hidden;         
+        }
+    </style>
+</head>
+
+<body>    
+    <div id="host-element">
+    </div>
+    <script src="index.js"></script>
+</body>
+
+</html>

+ 134 - 0
nodeEditor/public/index.js

@@ -0,0 +1,134 @@
+var snippetUrl = "https://snippet.babylonjs.com";
+var currentSnippetToken;
+var previousHash = "";
+var nodeMaterial;
+
+var customLoadObservable = new BABYLON.Observable();
+var editorDisplayed = false;
+
+var cleanHash = function () {
+    var splits = decodeURIComponent(location.hash.substr(1)).split("#");
+
+    if (splits.length > 2) {
+        splits.splice(2, splits.length - 2);
+    }
+
+    location.hash = splits.join("#");
+}
+
+var checkHash = function () {
+    if (location.hash) {
+        if (previousHash != location.hash) {
+            cleanHash();
+
+            previousHash = location.hash;
+
+            try {
+                var xmlHttp = new XMLHttpRequest();
+                xmlHttp.onreadystatechange = function () {
+                    if (xmlHttp.readyState == 4) {
+                        if (xmlHttp.status == 200) {
+                            var snippet = JSON.parse(JSON.parse(xmlHttp.responseText).jsonPayload);
+                            let serializationObject = JSON.parse(snippet.nodeMaterial);
+
+                            if (editorDisplayed) {
+                                customLoadObservable.notifyObservers(serializationObject);
+                            } else {
+                                nodeMaterial.loadFromSerialization(serializationObject);
+                                try {
+                                    nodeMaterial.build(true);
+                                } catch (err) {
+                                     // Swallow the error here
+                                }
+                                showEditor();
+                            }
+                        }
+                    }
+                }
+
+                var hash = location.hash.substr(1);
+                currentSnippetToken = hash.split("#")[0];
+                xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
+                xmlHttp.send();
+            } catch (e) {
+
+            }
+        }
+    }
+
+    setTimeout(checkHash, 200);
+}
+
+var showEditor = function() {
+    editorDisplayed = true;
+    var hostElement = document.getElementById("host-element");
+
+    BABYLON.NodeEditor.Show({
+        nodeMaterial: nodeMaterial, 
+        hostElement: hostElement,
+        customLoadObservable: customLoadObservable,
+        customSave: {
+            label: "Save as unique URL",
+            action: (data) => {
+                return new Promise((resolve, reject) => {
+                    var xmlHttp = new XMLHttpRequest();
+                    xmlHttp.onreadystatechange = function () {
+                        if (xmlHttp.readyState == 4) {
+                            if (xmlHttp.status == 200) {
+                                var baseUrl = location.href.replace(location.hash, "").replace(location.search, "");
+                                var snippet = JSON.parse(xmlHttp.responseText);
+                                var newUrl = baseUrl + "#" + snippet.id;
+                                currentSnippetToken = snippet.id;
+                                if (snippet.version && snippet.version != "0") {
+                                    newUrl += "#" + snippet.version;
+                                }
+                                location.href = newUrl;
+                                resolve();
+                            }
+                            else {
+                                reject(`Unable to save your node material. It may be too large (${(dataToSend.payload.length / 1024).toFixed(2)} KB) because of embedded textures. Please reduce texture sizes or point to a specific url instead of embedding them and try again.`);
+                            }
+                        }
+                    }
+        
+                    xmlHttp.open("POST", snippetUrl + (currentSnippetToken ? "/" + currentSnippetToken : ""), true);
+                    xmlHttp.setRequestHeader("Content-Type", "application/json");
+        
+                    var dataToSend = {
+                        payload : JSON.stringify({
+                            nodeMaterial: data
+                        }),
+                        name: "",
+                        description: "",
+                        tags: ""
+                    };
+        
+                    xmlHttp.send(JSON.stringify(dataToSend));
+                });
+            }
+        }
+    });
+}
+
+// Let's start
+if (BABYLON.Engine.isSupported()) {
+    var canvas = document.createElement("canvas");
+    var engine = new BABYLON.Engine(canvas, false, {disableWebGL2Support: true});
+    var scene = new BABYLON.Scene(engine);    
+    var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
+
+    nodeMaterial = new BABYLON.NodeMaterial("node");
+
+    // Set to default
+    if (!location.hash) {
+        nodeMaterial.setToDefault();
+        nodeMaterial.build(true);
+        showEditor();
+    }
+
+}
+else {
+    alert('Babylon.js is not supported.')
+}
+
+checkHash();

+ 26 - 14
nodeEditor/src/blockTools.ts

@@ -30,13 +30,17 @@ import { DivideBlock } from 'babylonjs/Materials/Node/Blocks/divideBlock';
 import { SubtractBlock } from 'babylonjs/Materials/Node/Blocks/subtractBlock';
 import { StepBlock } from 'babylonjs/Materials/Node/Blocks/stepBlock';
 import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
-import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
+import { NodeMaterialSystemValues } from 'babylonjs/Materials/Node/nodeMaterialSystemValues';
 import { AnimatedInputBlockTypes } from 'babylonjs/Materials/Node/Blocks/Input/animatedInputBlockTypes';
-import { OppositeBlock } from 'babylonjs/Materials/Node/Blocks/oppositeBlock';
+import { OneMinusBlock } from 'babylonjs/Materials/Node/Blocks/oneMinusBlock';
 import { ViewDirectionBlock } from 'babylonjs/Materials/Node/Blocks/viewDirectionBlock';
 import { LightInformationBlock } from 'babylonjs/Materials/Node/Blocks/Vertex/lightInformationBlock';
 import { MaxBlock } from 'babylonjs/Materials/Node/Blocks/maxBlock';
 import { MinBlock } from 'babylonjs/Materials/Node/Blocks/minBlock';
+import { PerturbNormalBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/perturbNormalBlock';
+import { LengthBlock } from 'babylonjs/Materials/Node/Blocks/lengthBlock';
+import { DistanceBlock } from 'babylonjs/Materials/Node/Blocks/distanceBlock';
+import { NegateBlock } from 'babylonjs/Materials/Node/Blocks/negateBlock';
 
 export class BlockTools {
     public static GetBlockFromString(data: string) {
@@ -78,7 +82,7 @@ export class BlockTools {
             case "ScaleBlock":
                 return new ScaleBlock("Scale");
             case "CrossBlock":
-                return new CrossBlock("Dot");
+                return new CrossBlock("Cross");
             case "DotBlock":
                 return new DotBlock("Dot");
             case "MultiplyBlock":
@@ -101,8 +105,8 @@ export class BlockTools {
                 return new SubtractBlock("Subtract"); 
             case "StepBlock":
                 return new StepBlock("Step");        
-            case "OppositeBlock":
-                return new OppositeBlock("Opposite");      
+            case "OneMinusBlock":
+                return new OneMinusBlock("One minus");      
             case "ViewDirectionBlock":
                 return new ViewDirectionBlock("View direction");    
             case "LightInformationBlock":
@@ -110,7 +114,15 @@ export class BlockTools {
             case "MaxBlock":
                 return new MaxBlock("Max");       
             case "MinBlock":
-                return new MinBlock("Min");                                                  
+                return new MinBlock("Min");      
+            case "LengthBlock":
+                return new LengthBlock("Length");   
+            case "DistanceBlock":
+                return new DistanceBlock("Distance");     
+            case "NegateBlock":
+                return new NegateBlock("Negate");                                     
+            case "PerturbNormalBlock":                                          
+                return new PerturbNormalBlock("Perturb normal");        
             case "CosBlock": {
                 let cosBlock = new TrigonometryBlock("Cos");
                 cosBlock.operation = TrigonometryBlockOperations.Cos;
@@ -153,42 +165,42 @@ export class BlockTools {
             }       
             case "WorldMatrixBlock": {
                 let worldMatrixBlock = new InputBlock("World");
-                worldMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.World);
+                worldMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.World);
                 return worldMatrixBlock;
             }             
             case "WorldViewMatrixBlock": {
                 let worldViewMatrixBlock = new InputBlock("World x View");
-                worldViewMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.WorldView);
+                worldViewMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.WorldView);
                 return worldViewMatrixBlock;
             }             
             case "WorldViewProjectionMatrixBlock": {
                 let worldViewProjectionMatrixBlock = new InputBlock("World x View x Projection");
-                worldViewProjectionMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.WorldViewProjection);
+                worldViewProjectionMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.WorldViewProjection);
                 return worldViewProjectionMatrixBlock;
             }                    
             case "ViewMatrixBlock": {
                 let viewMatrixBlock = new InputBlock("View");
-                viewMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.View);
+                viewMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.View);
                 return viewMatrixBlock;
             }                          
             case "ViewProjectionMatrixBlock": {
                 let viewProjectionMatrixBlock = new InputBlock("View x Projection");
-                viewProjectionMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.ViewProjection);
+                viewProjectionMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.ViewProjection);
                 return viewProjectionMatrixBlock;
             }                              
             case "ProjectionMatrixBlock": {
                 let projectionMatrixBlock = new InputBlock("Projection");
-                projectionMatrixBlock.setAsWellKnownValue(NodeMaterialWellKnownValues.Projection);
+                projectionMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.Projection);
                 return projectionMatrixBlock;
             }                                 
             case "CameraPositionBlock": {
                 let cameraPosition = new InputBlock("Camera position");
-                cameraPosition.setAsWellKnownValue(NodeMaterialWellKnownValues.CameraPosition);
+                cameraPosition.setAsSystemValue(NodeMaterialSystemValues.CameraPosition);
                 return cameraPosition;
             }                              
             case "FogColorBlock": {
                 let FogColor = new InputBlock("Fog color");
-                FogColor.setAsWellKnownValue(NodeMaterialWellKnownValues.FogColor);
+                FogColor.setAsSystemValue(NodeMaterialSystemValues.FogColor);
                 return FogColor;
             }                                   
             case "PositionBlock": {

+ 3 - 2
nodeEditor/src/components/diagram/diagram.scss

@@ -68,7 +68,7 @@
         background: #4086BB;
 
         .value {
-            grid-row: 2;
+            grid-row: 3;
         }
 
         .outputs, .inputs {
@@ -97,7 +97,8 @@
         border-top-left-radius: 16px;
         font-size: 16px;
         text-align: center;
-        margin-top: -1px;
+        margin-top: -1px;    
+        transform: scaleX(1.001);
         
         white-space: nowrap;
         text-overflow: ellipsis;

+ 8 - 1
nodeEditor/src/components/diagram/generic/genericNodeModel.tsx

@@ -64,7 +64,14 @@ export class GenericNodeModel extends DefaultNodeModel {
                         globalState.onRebuildRequiredObservable.notifyObservers();
                     }} isSelected={() => (this.block as TransformBlock).complementW === 0} />
                 </LineContainerComponent>
-            }        
+            }                    
+            {
+                this.block!.getClassName() === "PerturbNormalBlock" &&
+                <LineContainerComponent title="PROPERTIES">
+                    <CheckBoxLineComponent label="Invert X axis" target={this.block} propertyName="invertX" onValueChanged={() => globalState.onRebuildRequiredObservable.notifyObservers()} />
+                    <CheckBoxLineComponent label="Invert Y axis" target={this.block} propertyName="invertY" onValueChanged={() => globalState.onRebuildRequiredObservable.notifyObservers()}/>                    
+                </LineContainerComponent>
+            }   
             </div>
         );
     }

+ 60 - 28
nodeEditor/src/components/diagram/input/inputNodePropertyComponent.tsx

@@ -6,7 +6,7 @@ import { GlobalState } from '../../../globalState';
 import { InputNodeModel } from './inputNodeModel';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { OptionsLineComponent } from '../../../sharedComponents/optionsLineComponent';
-import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
+import { NodeMaterialSystemValues } from 'babylonjs/Materials/Node/nodeMaterialSystemValues';
 import { TextLineComponent } from '../../../sharedComponents/textLineComponent';
 import { Color3PropertyTabComponent } from '../../propertyTab/properties/color3PropertyTabComponent';
 import { FloatPropertyTabComponent } from '../../propertyTab/properties/floatPropertyTabComponent';
@@ -15,6 +15,10 @@ import { StringTools } from '../../../stringTools';
 import { AnimatedInputBlockTypes } from 'babylonjs/Materials/Node/Blocks/Input/animatedInputBlockTypes';
 import { TextInputLineComponent } from '../../../sharedComponents/textInputLineComponent';
 import { CheckBoxLineComponent } from '../../../sharedComponents/checkBoxLineComponent';
+import { Vector4PropertyTabComponent } from '../../propertyTab/properties/vector4PropertyTabComponent';
+import { MatrixPropertyTabComponent } from '../../propertyTab/properties/matrixPropertyTabComponent';
+import { FloatLineComponent } from '../../../sharedComponents/floatLineComponent';
+import { SliderLineComponent } from '../../../sharedComponents/sliderLineComponent';
 
 interface IInputPropertyTabComponentProps {
     globalState: GlobalState;
@@ -30,10 +34,30 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
     renderValue(globalState: GlobalState) {
         let inputBlock = this.props.inputNode.inputBlock;
         switch (inputBlock.type) {
-            case NodeMaterialBlockConnectionPointTypes.Float:
+            case NodeMaterialBlockConnectionPointTypes.Float: {
+                let cantDisplaySlider = (isNaN(inputBlock.min) || isNaN(inputBlock.max) || inputBlock.min === inputBlock.max);
                 return (
-                    <FloatPropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
+                    <>
+                        <FloatLineComponent label="Min" target={inputBlock} propertyName="min" onChange={() => {
+                            this.forceUpdate();
+                        }}></FloatLineComponent>
+                        <FloatLineComponent label="Max" target={inputBlock} propertyName="max" onChange={() => {
+                            this.forceUpdate();
+                        }}></FloatLineComponent>      
+
+                        {
+                            cantDisplaySlider &&
+                            <FloatPropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
+                        }        
+                        {
+                            !cantDisplaySlider &&
+                            <SliderLineComponent label="Value" target={inputBlock} propertyName="value" step={0.1} minimum={inputBlock.min} maximum={inputBlock.max} onChange={() => {
+                                this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                            }}/>
+                        }
+                    </>
                 );
+            }
             case NodeMaterialBlockConnectionPointTypes.Vector2:
                 return (
                     <Vector2PropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
@@ -46,7 +70,15 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
             case NodeMaterialBlockConnectionPointTypes.Vector3:
                 return (
                     <Vector3PropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
+                );            
+            case NodeMaterialBlockConnectionPointTypes.Vector4:
+                return (
+                    <Vector4PropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
                 );
+            case NodeMaterialBlockConnectionPointTypes.Matrix:
+                return (
+                    <MatrixPropertyTabComponent globalState={globalState} inputBlock={inputBlock} />
+                );                
         }
 
         return null;
@@ -60,7 +92,7 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
     render() {
         let inputBlock = this.props.inputNode.inputBlock;
 
-        var wellKnownOptions: {label: string, value: NodeMaterialWellKnownValues}[] = [];
+        var systemValuesOptions: {label: string, value: NodeMaterialSystemValues}[] = [];
         var attributeOptions: {label: string, value: string}[] = [];
         var animationOptions: {label: string, value: AnimatedInputBlockTypes}[] = [];
 
@@ -72,18 +104,18 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                 ];
                 break;      
             case NodeMaterialBlockConnectionPointTypes.Matrix:
-                wellKnownOptions = [
-                    { label: "World", value: NodeMaterialWellKnownValues.World },
-                    { label: "WorldxView", value: NodeMaterialWellKnownValues.WorldView },
-                    { label: "WorldxViewxProjection", value: NodeMaterialWellKnownValues.WorldViewProjection },
-                    { label: "View", value: NodeMaterialWellKnownValues.View },
-                    { label: "ViewxProjection", value: NodeMaterialWellKnownValues.ViewProjection },
-                    { label: "Projection", value: NodeMaterialWellKnownValues.Projection }
+                systemValuesOptions = [
+                    { label: "World", value: NodeMaterialSystemValues.World },
+                    { label: "World x View", value: NodeMaterialSystemValues.WorldView },
+                    { label: "World x ViewxProjection", value: NodeMaterialSystemValues.WorldViewProjection },
+                    { label: "View", value: NodeMaterialSystemValues.View },
+                    { label: "View x Projection", value: NodeMaterialSystemValues.ViewProjection },
+                    { label: "Projection", value: NodeMaterialSystemValues.Projection }
                 ];
                 break;
             case NodeMaterialBlockConnectionPointTypes.Color3:
-                wellKnownOptions = [
-                    { label: "Fog color", value: NodeMaterialWellKnownValues.FogColor }
+                systemValuesOptions = [
+                    { label: "Fog color", value: NodeMaterialSystemValues.FogColor }
                 ];
                 break;
             case NodeMaterialBlockConnectionPointTypes.Color4:
@@ -98,8 +130,8 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                 ];
                 break;                
             case NodeMaterialBlockConnectionPointTypes.Vector3:
-                wellKnownOptions = [
-                    { label: "Camera position", value: NodeMaterialWellKnownValues.CameraPosition }
+                systemValuesOptions = [
+                    { label: "Camera position", value: NodeMaterialSystemValues.CameraPosition }
                 ];
                 attributeOptions = [
                     { label: "position", value: "position" },
@@ -123,8 +155,8 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
             modeOptions.push({ label: "Mesh attribute", value: 1 });
         }
 
-        if (wellKnownOptions.length > 0) {
-            modeOptions.push({ label: "Well-known value", value: 2 });
+        if (systemValuesOptions.length > 0) {
+            modeOptions.push({ label: "System value", value: 2 });
         }
 
         return (
@@ -137,6 +169,10 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                     <TextLineComponent label="Type" value={StringTools.GetBaseType(inputBlock.type)} />
                 </LineContainerComponent>
                 <LineContainerComponent title="PROPERTIES">
+                    {
+                        inputBlock.isUniform && !inputBlock.isSystemValue && inputBlock.animationType === AnimatedInputBlockTypes.None &&
+                        <CheckBoxLineComponent label="Visible in the Inspector" target={inputBlock} propertyName="visibleInInspector"/>
+                    }                 
                     <OptionsLineComponent label="Mode" options={modeOptions} target={inputBlock} 
                         noDirectUpdate={true}
                         getSelection={(block) => {
@@ -144,7 +180,7 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                                 return 1;
                             }
 
-                            if (block.isWellKnownValue) {
+                            if (block.isSystemValue) {
                                 return 2;
                             }
 
@@ -154,14 +190,14 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                             switch (value) {
                                 case 0:
                                     inputBlock.isUniform = true;
-                                    inputBlock.setAsWellKnownValue(null);
+                                    inputBlock.setAsSystemValue(null);
                                     this.setDefaultValue();
                                     break;
                                 case 1:
                                     inputBlock.setAsAttribute(attributeOptions[0].value);
                                     break;
                                 case 2:
-                                    inputBlock.setAsWellKnownValue(wellKnownOptions[0].value);
+                                    inputBlock.setAsSystemValue(systemValuesOptions[0].value);
                                     break;
                             }
                             this.forceUpdate();
@@ -183,17 +219,13 @@ export class InputPropertyTabComponentProps extends React.Component<IInputProper
                         }} />
                     }   
                     {
-                        inputBlock.isUniform && !inputBlock.isWellKnownValue && inputBlock.animationType === AnimatedInputBlockTypes.None &&
-                        <CheckBoxLineComponent label="Visible in the Inspector" target={inputBlock} propertyName="visibleInInspector"/>
-                    }                 
-                    {
-                        inputBlock.isUniform && !inputBlock.isWellKnownValue && inputBlock.animationType === AnimatedInputBlockTypes.None &&
+                        inputBlock.isUniform && !inputBlock.isSystemValue && inputBlock.animationType === AnimatedInputBlockTypes.None &&
                         this.renderValue(this.props.globalState)
                     }
                     {
-                        inputBlock.isUniform && inputBlock.isWellKnownValue &&
-                        <OptionsLineComponent label="Well known value" options={wellKnownOptions} target={inputBlock} propertyName="wellKnownValue" onSelect={(value: any) => {
-                            inputBlock.setAsWellKnownValue(value);
+                        inputBlock.isUniform && inputBlock.isSystemValue &&
+                        <OptionsLineComponent label="System value" options={systemValuesOptions} target={inputBlock} propertyName="systemValue" onSelect={(value: any) => {
+                            inputBlock.setAsSystemValue(value);
                             this.forceUpdate();
                             this.props.globalState.onRebuildRequiredObservable.notifyObservers();
                         }} />

+ 11 - 11
nodeEditor/src/components/diagram/input/inputNodeWidget.tsx

@@ -2,7 +2,7 @@ import * as React from "react";
 import { InputNodeModel } from './inputNodeModel';
 import { Nullable } from 'babylonjs/types';
 import { GlobalState } from '../../../globalState';
-import { NodeMaterialWellKnownValues } from 'babylonjs/Materials/Node/nodeMaterialWellKnownValues';
+import { NodeMaterialSystemValues } from 'babylonjs/Materials/Node/nodeMaterialSystemValues';
 import { NodeMaterialBlockConnectionPointTypes } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPointTypes';
 import { Color3, Vector2, Vector3, Vector4 } from 'babylonjs/Maths/math';
 import { StringTools } from '../../../stringTools';
@@ -63,30 +63,30 @@ export class InputNodeWidget extends React.Component<IInputNodeWidgetProps> {
             if (inputBlock.isAttribute) {
                 value = "mesh." + inputBlock.name;
                 name = StringTools.GetBaseType(inputBlock.output.type);
-            } else if (inputBlock.isWellKnownValue) {
-                switch (inputBlock.wellKnownValue) {
-                    case NodeMaterialWellKnownValues.World:
+            } else if (inputBlock.isSystemValue) {
+                switch (inputBlock.systemValue) {
+                    case NodeMaterialSystemValues.World:
                         value = "World";
                         break;
-                    case NodeMaterialWellKnownValues.WorldView:
+                    case NodeMaterialSystemValues.WorldView:
                         value = "World x View";
                         break;
-                    case NodeMaterialWellKnownValues.WorldViewProjection:
+                    case NodeMaterialSystemValues.WorldViewProjection:
                         value = "World x View x Projection";
                         break;
-                    case NodeMaterialWellKnownValues.View:
+                    case NodeMaterialSystemValues.View:
                         value = "View";
                         break;
-                    case NodeMaterialWellKnownValues.ViewProjection:
+                    case NodeMaterialSystemValues.ViewProjection:
                         value = "View x Projection";
                         break;
-                    case NodeMaterialWellKnownValues.Projection:
+                    case NodeMaterialSystemValues.Projection:
                         value = "Projection";
                         break;
-                    case NodeMaterialWellKnownValues.CameraPosition:
+                    case NodeMaterialSystemValues.CameraPosition:
                         value = "Camera position";
                         break;
-                    case NodeMaterialWellKnownValues.FogColor:
+                    case NodeMaterialSystemValues.FogColor:
                         value = "Fog color";
                         break;
                 }

+ 24 - 3
nodeEditor/src/components/diagram/remap/remapNodeWidget.tsx

@@ -4,6 +4,8 @@ import { Nullable } from 'babylonjs/types';
 import { GlobalState } from '../../../globalState';
 import { PortHelper } from '../portHelper';
 import { RemapBlock } from 'babylonjs/Materials/Node/Blocks/remapBlock';
+import { NodeMaterialConnectionPoint } from 'babylonjs/Materials/Node/nodeMaterialBlockConnectionPoint';
+import { InputBlock } from 'babylonjs/Materials/Node/Blocks/Input/inputBlock';
 
 /**
  * RemapNodeWidgetProps
@@ -47,11 +49,30 @@ export class RemapNodeWidget extends React.Component<RemapNodeWidgetProps> {
         return null;
     }
 
+    extractInputValue(connectionPoint: NodeMaterialConnectionPoint) {
+        let connectedBlock = connectionPoint.connectedPoint!.ownerBlock;
+
+        if (connectedBlock.isInput) {
+            let inputBlock = connectedBlock as InputBlock;
+
+            if (inputBlock.isUniform && !inputBlock.isSystemValue) {
+                return inputBlock.value;
+            }
+        }
+
+        return "?";
+    }
+
     render() {
-        var inputPorts = PortHelper.GenerateInputPorts(this.props.node, undefined, true);
-        var outputPorts = PortHelper.GenerateOutputPorts(this.props.node, true);
+        var inputPorts = PortHelper.GenerateInputPorts(this.props.node, undefined, false);
+        var outputPorts = PortHelper.GenerateOutputPorts(this.props.node, false);
         let remapBlock = this.props.node!.block! as RemapBlock;
 
+        let sourceRangeX = remapBlock.sourceMin.isConnected ? this.extractInputValue(remapBlock.sourceMin) : remapBlock.sourceRange.x;
+        let sourceRangeY = remapBlock.sourceMax.isConnected ? this.extractInputValue(remapBlock.sourceMax) : remapBlock.sourceRange.y;
+        let targetRangeX = remapBlock.targetMin.isConnected ? this.extractInputValue(remapBlock.targetMin) : remapBlock.targetRange.x;
+        let targetRangeY = remapBlock.targetMax.isConnected ? this.extractInputValue(remapBlock.targetMax) : remapBlock.targetRange.y;
+
         return (
             <div className={"diagramBlock remap"}>
                 <div className="header">
@@ -65,7 +86,7 @@ export class RemapNodeWidget extends React.Component<RemapNodeWidgetProps> {
                 </div>
                 <div className="value">  
                 {
-                    `[${remapBlock.sourceRange.x}, ${remapBlock.sourceRange.y}] -> [${remapBlock.targetRange.x}, ${remapBlock.targetRange.y}]`
+                    `[${sourceRangeX}, ${sourceRangeY}] -> [${targetRangeX}, ${targetRangeY}]`
                 }                 
                 </div>
             </div>

+ 3 - 3
nodeEditor/src/components/diagram/texture/textureNodeModel.tsx

@@ -1,12 +1,12 @@
 import * as React from 'react';
 import { Nullable } from 'babylonjs/types';
-import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
 import { DefaultNodeModel } from '../defaultNodeModel';
 import { GlobalState } from '../../../globalState';
 import { TexturePropertyTabComponent } from './texturePropertyTabComponent';
 import { NodeCreationOptions, GraphEditor } from '../../../graphEditor';
 import { DiagramModel } from 'storm-react-diagrams/dist/@types/src/models/DiagramModel';
 import { TextureBlock } from 'babylonjs/Materials/Node/Blocks/Dual/textureBlock';
+import { Texture } from 'babylonjs/Materials/Textures/texture';
 
 /**
  * Texture node model which stores information about a node editor block
@@ -17,11 +17,11 @@ export class TextureNodeModel extends DefaultNodeModel {
 	/**
 	 * Texture for the node if it exists
 	 */
-    public get texture(): Nullable<BaseTexture> {
+    public get texture(): Nullable<Texture> {
         return this._block.texture;
     }
 
-    public set texture(value: Nullable<BaseTexture>) {
+    public set texture(value: Nullable<Texture>) {
         this._block.texture = value;
     }
 

+ 115 - 4
nodeEditor/src/components/diagram/texture/texturePropertyTabComponent.tsx

@@ -10,13 +10,24 @@ import { LineContainerComponent } from '../../../sharedComponents/lineContainerC
 import { TextInputLineComponent } from '../../../sharedComponents/textInputLineComponent';
 import { CheckBoxLineComponent } from '../../../sharedComponents/checkBoxLineComponent';
 import { Texture } from 'babylonjs/Materials/Textures/texture';
+import { SliderLineComponent } from '../../../sharedComponents/sliderLineComponent';
+import { FloatLineComponent } from '../../../sharedComponents/floatLineComponent';
 
 interface ITexturePropertyTabComponentProps {
     globalState: GlobalState;
     node: TextureNodeModel;
 }
 
-export class TexturePropertyTabComponent extends React.Component<ITexturePropertyTabComponentProps> {
+export class TexturePropertyTabComponent extends React.Component<ITexturePropertyTabComponentProps, {isEmbedded: boolean}> {
+
+    constructor(props: ITexturePropertyTabComponentProps) {
+        super(props);
+
+        let texture = this.props.node.texture as BaseTexture;
+
+        this.state = {isEmbedded: !texture || texture.name.substring(0, 4) !== "http"};
+    }
+
 
     updateAftertextureLoad() {
         this.props.globalState.onUpdateRequiredObservable.notifyObservers();
@@ -34,7 +45,7 @@ export class TexturePropertyTabComponent extends React.Component<ITexturePropert
 
         let texture = this.props.node.texture as BaseTexture;
         if (!texture) {
-            this.props.node.texture = new Texture(null, this.props.globalState.nodeMaterial.getScene(), false, false)
+            this.props.node.texture = new Texture(null, this.props.globalState.nodeMaterial.getScene(), false, false);
             texture = this.props.node.texture;
         }
 
@@ -62,17 +73,117 @@ export class TexturePropertyTabComponent extends React.Component<ITexturePropert
         }, undefined, true);
     }
 
+    replaceTextureWithUrl(url: string) {
+        let texture = this.props.node.texture as BaseTexture;
+        if (!texture) {
+            this.props.node.texture = new Texture(url, this.props.globalState.nodeMaterial.getScene(), false, false, undefined, () => {
+                this.updateAftertextureLoad();
+            });
+            return;
+        }
+
+        (texture as Texture).updateURL(url, null, () => this.updateAftertextureLoad());
+    }
+
     render() {
+        let url = "";
+
+        let texture = this.props.node.texture as BaseTexture;
+        if (texture && texture.name && texture.name.substring(0, 4) === "http") {
+            url = texture.name;
+        }
+
         return (
             <div>
                 <LineContainerComponent title="GENERAL">
                     <TextLineComponent label="Type" value="Texture" />
                     <TextInputLineComponent globalState={this.props.globalState} label="Name" propertyName="name" target={this.props.node.block!} onChange={() => this.props.globalState.onUpdateRequiredObservable.notifyObservers()} />
                 </LineContainerComponent>
-
                 <LineContainerComponent title="PROPERTIES">
                     <CheckBoxLineComponent label="Auto select UV" propertyName="autoSelectUV" target={this.props.node.block!} />
-                    <FileButtonLineComponent label="Replace texture" onClick={(file) => this.replaceTexture(file)} accept=".jpg, .png, .tga, .dds, .env" />
+                    {
+                        texture &&
+                        <CheckBoxLineComponent label="Clamp U" isSelected={() => texture.wrapU === Texture.CLAMP_ADDRESSMODE} onSelect={(value) => {
+                            texture.wrapU = value ? Texture.CLAMP_ADDRESSMODE : Texture.WRAP_ADDRESSMODE;
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }} />
+                    }
+                    {
+                        texture &&
+                        <CheckBoxLineComponent label="Clamp V" isSelected={() => texture.wrapV === Texture.CLAMP_ADDRESSMODE} onSelect={(value) => {
+                            texture.wrapV = value ? Texture.CLAMP_ADDRESSMODE : Texture.WRAP_ADDRESSMODE;
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }} />
+                    }        
+                    {
+                        texture &&
+                        <FloatLineComponent label="Offset U" target={texture} propertyName="uOffset" 
+                        onChange={() => {
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }}
+                        />
+                    }
+                    {
+                        texture &&
+                        <FloatLineComponent label="Offset U" target={texture} propertyName="vOffset"
+                        onChange={() => {
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }}
+                        />
+                    }
+                    {
+                        texture &&
+                        <FloatLineComponent label="Scale U" target={texture} propertyName="uScale"
+                        onChange={() => {
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }} />
+                    }
+                    {
+                        texture &&
+                        <FloatLineComponent label="Scale V" target={texture} propertyName="vScale"
+                        onChange={() => {
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }} />
+                    }
+                    {
+                        texture &&
+                        <SliderLineComponent label="Rotation U" target={texture} propertyName="uAng" minimum={0} maximum={Math.PI * 2} useEuler={true} step={0.1}
+                        onChange={() => {
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }}
+                        />
+                    }
+                    {
+                        texture &&
+                        <SliderLineComponent label="Rotation V" target={texture} propertyName="vAng" minimum={0} maximum={Math.PI * 2} useEuler={true} step={0.1}
+                        onChange={() => {
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }}
+                        />
+                    }                    
+                    {
+                        texture &&
+                        <SliderLineComponent label="Rotation W" target={texture} propertyName="wAng" minimum={0} maximum={Math.PI * 2} useEuler={true} step={0.1}
+                        onChange={() => {
+                            this.props.globalState.onUpdateRequiredObservable.notifyObservers();
+                        }}
+                        />
+                    }
+                </LineContainerComponent>
+                <LineContainerComponent title="SOURCE">
+                    <CheckBoxLineComponent label="Embed texture" isSelected={() => this.state.isEmbedded} onSelect={value => {
+                        this.setState({isEmbedded: value});
+                        this.props.node.texture = null;
+                        this.updateAftertextureLoad();
+                    }}/>
+                    {
+                        this.state.isEmbedded &&
+                        <FileButtonLineComponent label="Upload" onClick={(file) => this.replaceTexture(file)} accept=".jpg, .png, .tga, .dds, .env" />
+                    }
+                    {
+                        !this.state.isEmbedded &&
+                        <TextInputLineComponent label="Link" globalState={this.props.globalState} value={url} onChange={newUrl => this.replaceTextureWithUrl(newUrl)}/>
+                    }
                 </LineContainerComponent>
             </div>
         );

+ 0 - 1
nodeEditor/src/components/log/log.scss

@@ -1,6 +1,5 @@
 #log-console {
     background: #333333;
-    border: #555555 solid 1px;
     height: 120px;
     box-sizing: border-box;
     margin: 0;

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

@@ -49,7 +49,7 @@
             .list-container {
                 overflow-x: hidden;
                 overflow-y: auto;
-                height: 100%;
+                height: calc(100% - 32px);
 
                 .underline {
                     border-bottom: 0.5px solid rgba(255, 255, 255, 0.5);

+ 3 - 3
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -26,7 +26,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         // Block types used to create the menu from
         const allBlocks = {
             Animation: ["BonesBlock", "MorphTargetsBlock"],
-            Basic_Math: ["AddBlock",  "DivideBlock", "MultiplyBlock", "ScaleBlock", "SubtractBlock", "OppositeBlock", "MaxBlock", "MinBlock"],
+            Basic_Math: ["AddBlock",  "DivideBlock", "MultiplyBlock", "ScaleBlock", "SubtractBlock", "OneMinusBlock", "MaxBlock", "MinBlock", "LengthBlock", "DistanceBlock", "NegateBlock"],
             Conversion_Blocks: ["ColorMergerBlock", "ColorSplitterBlock", "VectorMergerBlock", "VectorSplitterBlock"],
             Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "TextureBlock", "TimeBlock"],
             Interpolation: ["LerpBlock"],
@@ -35,7 +35,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
             Output_Blocks: ["VertexOutputBlock", "FragmentOutputBlock", "AlphaTestBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Round: ["StepBlock", "RoundBlock", "CeilingBlock", "FloorBlock"],
-            Scene_Attributes: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ReflectionTextureBlock", "ViewDirectionBlock"],
+            Scene_Attributes: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ReflectionTextureBlock", "ViewDirectionBlock", "PerturbNormalBlock"],
             Trigonometry: ["CosBlock", "SinBlock", "AbsBlock", "ExpBlock", "Exp2Block"],
             Vector_Math: ["CrossBlock", "DotBlock", "TransformBlock", "FresnelBlock"],
         }
@@ -59,7 +59,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         }
 
         return (
-            <div id="nodeList" style={{ borderRightStyle: "solid", borderColor: "grey", borderWidth: "1px" }} >
+            <div id="nodeList">
                 <div className="panes">
                     <div className="pane">
                         <div className="filter">

+ 54 - 0
nodeEditor/src/components/preview/previewAreaComponent.tsx

@@ -0,0 +1,54 @@
+
+import * as React from "react";
+import { GlobalState } from '../../globalState';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faPlay, faStop, faPalette } from '@fortawesome/free-solid-svg-icons';
+import { Color3, Color4 } from 'babylonjs/Maths/math.color';
+import { DataStorage } from '../../dataStorage';
+
+interface IPreviewAreaComponent {
+    globalState: GlobalState;
+    width: number;
+}
+
+export class PreviewAreaComponent extends React.Component<IPreviewAreaComponent> {
+
+    changeAnimation() {
+        this.props.globalState.rotatePreview = !this.props.globalState.rotatePreview;
+        this.props.globalState.onAnimationCommandActivated.notifyObservers();
+        this.forceUpdate();
+    }
+
+    changeBackground(value: string) {
+        const newColor = Color3.FromHexString(value);
+
+        DataStorage.StoreNumber("BackgroundColorR", newColor.r);
+        DataStorage.StoreNumber("BackgroundColorG", newColor.g);
+        DataStorage.StoreNumber("BackgroundColorB", newColor.b);
+
+        this.props.globalState.backgroundColor = Color4.FromColor3(newColor, 1.0);
+        this.props.globalState.onPreviewBackgroundChanged.notifyObservers();
+    }
+
+    render() {
+        return (
+            <>
+                <div id="preview" style={{height: this.props.width + "px"}}>
+                    <canvas id="preview-canvas"/>
+                </div>                
+                <div id="preview-config-bar">
+                    <div onClick={() => this.changeAnimation()} className={"button"}>
+                        <FontAwesomeIcon icon={this.props.globalState.rotatePreview ? faStop : faPlay} />
+                    </div>
+                    <div className={"button align"}>
+                        <label htmlFor="color-picker" id="color-picker-label">
+                            <FontAwesomeIcon icon={faPalette} />
+                        </label>
+                        <input ref="color-picker" id="color-picker" type="color" onChange={evt => this.changeBackground(evt.target.value)} />
+                    </div>
+                </div>
+            </>
+        );
+
+    }
+}

+ 139 - 30
nodeEditor/src/components/preview/previewManager.ts

@@ -9,19 +9,27 @@ import { Vector3 } from 'babylonjs/Maths/math.vector';
 import { HemisphericLight } from 'babylonjs/Lights/hemisphericLight';
 import { ArcRotateCamera } from 'babylonjs/Cameras/arcRotateCamera';
 import { PreviewMeshType } from './previewMeshType';
+import { Animation } from 'babylonjs/Animations/animation';
+import { SceneLoader } from 'babylonjs/Loading/sceneLoader';
+import { TransformNode } from 'babylonjs/Meshes/transformNode';
+import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh';
+import { FramingBehavior } from 'babylonjs/Behaviors/Cameras/framingBehavior';
 
 export class PreviewManager {
     private _nodeMaterial: NodeMaterial;
     private _onBuildObserver: Nullable<Observer<NodeMaterial>>;    
-    private _onPreviewMeshTypeChangedObserver: Nullable<Observer<void>>;
+    private _onPreviewCommandActivatedObserver: Nullable<Observer<void>>;
+    private _onAnimationCommandActivatedObserver: Nullable<Observer<void>>;
     private _onUpdateRequiredObserver: Nullable<Observer<void>>;
+    private _onPreviewBackgroundChangedObserver: Nullable<Observer<void>>;
     private _engine: Engine;
     private _scene: Scene;
     private _light: HemisphericLight;
-    private _dummy: Mesh;
+    private _meshes: AbstractMesh[];
     private _camera: ArcRotateCamera;
     private _material: NodeMaterial;
-    private _globalState: GlobalState;    
+    private _globalState: GlobalState;   
+    private _currentType: number; 
 
     public constructor(targetCanvas: HTMLCanvasElement, globalState: GlobalState) {
         this._nodeMaterial = globalState.nodeMaterial;
@@ -32,7 +40,7 @@ export class PreviewManager {
             this._updatePreview(serializationObject);
         });
 
-        this._onPreviewMeshTypeChangedObserver = globalState.onPreviewMeshTypeChanged.add(() => {
+        this._onPreviewCommandActivatedObserver = globalState.onPreviewCommandActivated.add(() => {
             this._refreshPreviewMesh();
         });
 
@@ -41,15 +49,23 @@ export class PreviewManager {
             this._updatePreview(serializationObject);
         });
 
+        this._onPreviewBackgroundChangedObserver = globalState.onPreviewBackgroundChanged.add(() => {
+            this._scene.clearColor = this._globalState.backgroundColor;    
+        });
+
+        this._onAnimationCommandActivatedObserver = globalState.onAnimationCommandActivated.add(() => {
+            this._handleAnimations();
+        });
+
         this._engine = new Engine(targetCanvas, true);
         this._scene = new Scene(this._engine);
         this._camera = new ArcRotateCamera("Camera", 0, 0.8, 4, Vector3.Zero(), this._scene);
         this._light = new HemisphericLight("light", new Vector3(0, 1, 0), this._scene);
 
-
         this._camera.lowerRadiusLimit = 3;
         this._camera.upperRadiusLimit = 10;
         this._camera.wheelPrecision = 20;
+        this._camera.minZ = 0.1;
         this._camera.attachControl(targetCanvas, false);
 
         this._refreshPreviewMesh();
@@ -63,49 +79,142 @@ export class PreviewManager {
         this._updatePreview(serializationObject);
     }
 
-    private _refreshPreviewMesh() {    
-        if (this._dummy) {
-            this._dummy.dispose();
+    private _handleAnimations() {
+        this._scene.stopAllAnimations();
+                        
+        if (this._globalState.rotatePreview) {
+            for (var root of this._scene.rootNodes) {
+                let transformNode = root as TransformNode;
+
+                if (transformNode.getClassName() === "TransformNode" || transformNode.getClassName() === "Mesh") {
+                    if (transformNode.rotationQuaternion) {
+                        transformNode.rotation = transformNode.rotationQuaternion.toEulerAngles();
+                        transformNode.rotationQuaternion = null;
+                    }
+                    Animation.CreateAndStartAnimation("turnTable", root, "rotation.y", 60, 1200, transformNode.rotation.y, transformNode.rotation.y + 2 * Math.PI, 1);
+                }
+            }
         }
+    }
+
+    private _prepareMeshes() {
+        // Material
+        for (var mesh of this._meshes) {
+            mesh.material = this._material;
+        }
+
+        // Framing
+        this._camera.useFramingBehavior = true;
+
+        var framingBehavior = this._camera.getBehaviorByName("Framing") as FramingBehavior;
+        framingBehavior.framingTime = 0;
+        framingBehavior.elevationReturnTime = -1;
+
+        if (this._scene.meshes.length) {
+            var worldExtends = this._scene.getWorldExtends();
+            this._camera.lowerRadiusLimit = null;
+            this._camera.upperRadiusLimit = null;
+            framingBehavior.zoomOnBoundingInfo(worldExtends.min, worldExtends.max);
+        }
+
+        this._camera.pinchPrecision = 200 / this._camera.radius;
+        this._camera.upperRadiusLimit = 5 * this._camera.radius;
+
+        this._camera.wheelDeltaPercentage = 0.01;
+        this._camera.pinchDeltaPercentage = 0.01;
+
+        // Animations
+        this._handleAnimations();
+    }
+
+    private _refreshPreviewMesh() {    
+
+        if (this._currentType !== this._globalState.previewMeshType || this._currentType === PreviewMeshType.Custom) {
+
+            this._currentType = this._globalState.previewMeshType;
+            if (this._meshes && this._meshes.length) {
+
+                for (var mesh of this._meshes) {
+                    mesh.dispose();
+                }
+            }
+
+            this._meshes = [];
         
-        switch (this._globalState.previewMeshType) {
-            case PreviewMeshType.Box:
-                this._dummy = Mesh.CreateBox("dummy-box", 2, this._scene);
-                break;
-            case PreviewMeshType.Sphere:
-                this._dummy = Mesh.CreateSphere("dummy-sphere", 32, 2, this._scene);
-                break;
-            case PreviewMeshType.Torus:
-                this._dummy = Mesh.CreateTorus("dummy-torus", 2, 0.5, 32, this._scene);
-                break;
+            switch (this._globalState.previewMeshType) {
+                case PreviewMeshType.Box:
+                    this._meshes.push(Mesh.CreateBox("dummy-box", 2, this._scene));
+                    break;
+                case PreviewMeshType.Sphere:
+                    this._meshes.push(Mesh.CreateSphere("dummy-sphere", 32, 2, this._scene));
+                    break;
+                case PreviewMeshType.Torus:
+                    this._meshes.push(Mesh.CreateTorus("dummy-torus", 2, 0.5, 32, this._scene));
+                    break;
                 case PreviewMeshType.Cylinder:
-                this._dummy = Mesh.CreateCylinder("dummy-cylinder", 2, 1, 1.2, 32, 1, this._scene);
-                break;                
+                    this._meshes.push(Mesh.CreateCylinder("dummy-cylinder", 2, 1, 1.2, 32, 1, this._scene));
+                    break;                
+                case PreviewMeshType.Plane:
+                    this._meshes.push(Mesh.CreateGround("dummy-plane", 2, 2, 128, this._scene));
+                    break;    
+                case PreviewMeshType.ShaderBall:
+                    SceneLoader.AppendAsync("https://models.babylonjs.com/", "shaderBall.glb", this._scene).then(() => {     
+                        this._meshes.push(...this._scene.meshes);
+                        this._prepareMeshes();
+                    });
+                    return;                             
+                case PreviewMeshType.Custom:
+                    SceneLoader.AppendAsync("file:", this._globalState.previewMeshFile, this._scene).then(() => {     
+                        this._meshes.push(...this._scene.meshes);
+                        this._prepareMeshes();
+                    });
+                    return;     
+            }
+            
+            this._prepareMeshes();
         }
-        this._dummy.material = this._material;
     }
 
     private _updatePreview(serializationObject: any) {
-        if (this._material) {
-            this._material.dispose();
-        }        
-
-        this._material = NodeMaterial.Parse(serializationObject, this._scene);
-        this._material.build();
-        this._dummy.material = this._material;
+        let tempMaterial = NodeMaterial.Parse(serializationObject, this._scene);
+        try {
+            tempMaterial.build();
+
+            if (this._meshes.length) {
+                tempMaterial.forceCompilation(this._meshes[0], () => {
+                    for (var mesh of this._meshes) {
+                        mesh.material = tempMaterial;
+                    }
+        
+                    if (this._material) {
+                        this._material.dispose();
+                    }      
+        
+                    this._material = tempMaterial;    
+                });
+            } else {
+                this._material = tempMaterial;    
+            }
+        } catch(err) {
+            // Ignore the error
+        }
     }
 
     public dispose() {
         this._nodeMaterial.onBuildObservable.remove(this._onBuildObserver);
-        this._globalState.onPreviewMeshTypeChanged.remove(this._onPreviewMeshTypeChangedObserver);
+        this._globalState.onPreviewCommandActivated.remove(this._onPreviewCommandActivatedObserver);
         this._globalState.onUpdateRequiredObservable.remove(this._onUpdateRequiredObserver);
+        this._globalState.onAnimationCommandActivated.remove(this._onAnimationCommandActivatedObserver);
+        this._globalState.onPreviewBackgroundChanged.remove(this._onPreviewBackgroundChangedObserver);
 
         if (this._material) {
             this._material.dispose();
         }
 
         this._camera.dispose();
-        this._dummy.dispose();
+        for (var mesh of this._meshes) {
+            mesh.dispose();
+        }
         this._light.dispose();
         this._engine.dispose();
     }

+ 27 - 2
nodeEditor/src/components/preview/previewMeshControlComponent.tsx

@@ -2,7 +2,7 @@
 import * as React from "react";
 import { GlobalState } from '../../globalState';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faCircle, faRing, faCube, faHockeyPuck } from '@fortawesome/free-solid-svg-icons';
+import { faCircle, faRing, faCube, faHockeyPuck, faSquareFull, faPlus, faDotCircle } from '@fortawesome/free-solid-svg-icons';
 import { PreviewMeshType } from './previewMeshType';
 import { DataStorage } from '../../dataStorage';
 
@@ -18,13 +18,26 @@ export class PreviewMeshControlComponent extends React.Component<IPreviewMeshCon
         }
 
         this.props.globalState.previewMeshType = newOne;
-        this.props.globalState.onPreviewMeshTypeChanged.notifyObservers();
+        this.props.globalState.onPreviewCommandActivated.notifyObservers();
 
         DataStorage.StoreNumber("PreviewMeshType", newOne);
 
         this.forceUpdate();
     }
 
+    useCustomMesh(evt: any) {
+        var files: File[] = evt.target.files;
+        if (files && files.length) {
+            let file = files[0];
+
+            this.props.globalState.previewMeshFile = file;
+            this.props.globalState.previewMeshType = PreviewMeshType.Custom;
+            this.props.globalState.onPreviewCommandActivated.notifyObservers();        
+            this.forceUpdate();
+        }
+        (document.getElementById("file-picker")! as HTMLInputElement).value = "";
+    }
+
     render() {
         return (
             <div id="preview-mesh-bar">
@@ -40,6 +53,18 @@ export class PreviewMeshControlComponent extends React.Component<IPreviewMeshCon
                 <div onClick={() => this.changeMeshType(PreviewMeshType.Cylinder)} className={"button" + (this.props.globalState.previewMeshType === PreviewMeshType.Cylinder ? " selected" : "")}>
                     <FontAwesomeIcon icon={faHockeyPuck} />
                 </div>
+                <div onClick={() => this.changeMeshType(PreviewMeshType.Plane)} className={"button" + (this.props.globalState.previewMeshType === PreviewMeshType.Plane ? " selected" : "")}>
+                    <FontAwesomeIcon icon={faSquareFull} />
+                </div>      
+                <div onClick={() => this.changeMeshType(PreviewMeshType.ShaderBall)} className={"button" + (this.props.globalState.previewMeshType === PreviewMeshType.ShaderBall ? " selected" : "")}>
+                    <FontAwesomeIcon icon={faDotCircle} />
+                </div>                           
+                <div className={"button align"}>
+                    <label htmlFor="file-picker" id="file-picker-label">
+                        <FontAwesomeIcon icon={faPlus} />
+                    </label>
+                    <input ref="file-picker" id="file-picker" type="file" onChange={evt => this.useCustomMesh(evt)} accept=".gltf, .glb, .babylon, .obj"/>
+                </div>
             </div>
         );
 

+ 0 - 0
nodeEditor/src/components/preview/previewMeshType.ts


Некоторые файлы не были показаны из-за большого количества измененных файлов